library(pprint)
library(haven)
library(Statamarkdown)
Stata found at C:/Program Files/Stata16/StataMP-64.exe
Warning: incomplete final line found on 'profile.do'Found an existing 'profile.do'
    
   cd "C:\Users\slupp\OneDrive\Skrivebord\NTNU\Mehmet\PSY8003\Dummy_moderation_and_mediation" 
    
   // section 1: dummmy variable regression 
   use flats.dta 
    
    
   // section 3: Mediation 
   *use workout.dta 

The 'stata' engine is ready to use.
library(dplyr)

Attaching package: ‘dplyr’

The following objects are masked from ‘package:stats’:

    filter, lag

The following objects are masked from ‘package:base’:

    intersect, setdiff, setequal, union

Section 1: Dummy Variable Regression

setwd("C:/Users/slupp/OneDrive/Skrivebord/NTNU/Mehmet/PSY8003/Dummy_moderation_and_mediation")
flats <- readRDS("flats.rds")
> nd_mediation"
C:\Users\slupp\OneDrive\Skrivebord\NTNU\Mehmet\PSY8003\Dummy_moderation_and_med
> iation

Comparing Means

  1. If we’re only using a single categorical variable in our regression it is akin to a t-test or a one-way ANOVA
  2. While we can create dummy variables in our dataset, both STATA and R have built in ways of handling categorical variables their regression command/function.
  3. For this to work it is important that our variable is coded correctly (i.e., as a factor), and it should also have labeled values
  4. Lets say we want to compare mean-prices for flats at different locations

Labeling Values

R

# NB the variable is already coded as a factor, so this is only to show how its done 
# SO DO NOT RUN/OVERWRITE ORIGINAL DATASET
flats2 <- flats %>% mutate(location = factor(location,
                                          levels = c(1, 2, 3, 4),
                                          labels = c("centre",
                                                     "south",
                                                     "west",
                                                     "east")))

STATA

location                                                            (unlabeled)
-------------------------------------------------------------------------------

                  type:  numeric (long)
                 label:  labels_location

                 range:  [1,4]                        units:  1
         unique values:  4                        missing .:  0/95

            tabulation:  Freq.   Numeric  Label
                            34         1  centre
                             9         2  south
                            11         3  west
                            41         4  east

Regression: Comparing Means Location

If our variable is coded correctly (as a factor) we can see that R automatically treats it as a (or rather mutiple) dummy variable(s)

reg_price_location <- lm(flat_price ~ location, data = flats)
preg(reg_price_location)
 
 
 
 Model fit: flat_price 
# Color data frame (class colorDF) 6 x 3:
        │SS      │df   │M.      │M    │R            │R.      
   Model│2.95e+11│    3│F(3, 91)│ 2.05│    R-squared│6.34e-02
Residual│4.36e+12│   91│prob > F│  0.1│adj R-squared│3.25e-02
   Total│4.65e+12│   94│       N│   95│          MSE│2.19e+05

 
 Coefficients: flat_price 
# Color data frame (class colorDF) 6 x 4:
             │ Coefficients│ std.error│ t-value│ p-value│ CI[2.5%]
  (Intercept)│       597721│     37524│   15.93│  <2e-16│   523183
locationsouth│      -172350│     82021│   -2.10│  0.0384│  -335275
 locationwest│       -83933│     75897│   -1.11│  0.2717│  -234692
 locationeast│       -97993│     50752│   -1.93│  0.0566│  -198805
             │ CI[97.5%]
  (Intercept)│    672258
locationsouth│     -9425
 locationwest│     66827
 locationeast│      2819

In STATA it is not that simple

      Source |       SS           df       MS      Number of obs   =        95
-------------+----------------------------------   F(1, 93)        =      2.90
       Model |  1.4083e+11         1  1.4083e+11   Prob > F        =    0.0917
    Residual |  4.5107e+12        93  4.8502e+10   R-squared       =    0.0303
-------------+----------------------------------   Adj R-squared   =    0.0198
       Total |  4.6515e+12        94  4.9484e+10   Root MSE        =    2.2e+05

------------------------------------------------------------------------------
  flat_price |      Coef.   Std. Err.      t    P>|t|     [95% Conf. Interval]
-------------+----------------------------------------------------------------
    location |  -28584.31      16775    -1.70   0.092    -61896.14    4727.521
       _cons |   604303.4   49434.23    12.22   0.000     506136.9      702470
------------------------------------------------------------------------------

In STATA we need to use a i. in front (Likewise we can force a categorical variable as continuous using c.)

      Source |       SS           df       MS      Number of obs   =        95
-------------+----------------------------------   F(3, 91)        =      2.05
       Model |  2.9488e+11         3  9.8294e+10   Prob > F        =    0.1120
    Residual |  4.3566e+12        91  4.7875e+10   R-squared       =    0.0634
-------------+----------------------------------   Adj R-squared   =    0.0325
       Total |  4.6515e+12        94  4.9484e+10   Root MSE        =    2.2e+05

------------------------------------------------------------------------------
  flat_price |      Coef.   Std. Err.      t    P>|t|     [95% Conf. Interval]
-------------+----------------------------------------------------------------
    location |
      south  |  -172350.2   82021.29    -2.10   0.038    -335275.4   -9424.993
       west  |  -83932.71   75896.81    -1.11   0.272    -234692.4    66826.99
       east  |  -97992.95    50751.9    -1.93   0.057    -198805.4    2819.474
             |
       _cons |   597720.6   37524.39    15.93   0.000       523183    672258.2
------------------------------------------------------------------------------

This works even if our variable lacks labels

      Source |       SS           df       MS      Number of obs   =        95
-------------+----------------------------------   F(3, 91)        =      2.05
       Model |  2.9488e+11         3  9.8294e+10   Prob > F        =    0.1120
    Residual |  4.3566e+12        91  4.7875e+10   R-squared       =    0.0634
-------------+----------------------------------   Adj R-squared   =    0.0325
       Total |  4.6515e+12        94  4.9484e+10   Root MSE        =    2.2e+05

------------------------------------------------------------------------------
  flat_price |      Coef.   Std. Err.      t    P>|t|     [95% Conf. Interval]
-------------+----------------------------------------------------------------
    location |
          2  |  -172350.2   82021.29    -2.10   0.038    -335275.4   -9424.993
          3  |  -83932.71   75896.81    -1.11   0.272    -234692.4    66826.99
          4  |  -97992.95    50751.9    -1.93   0.057    -198805.4    2819.474
             |
       _cons |   597720.6   37524.39    15.93   0.000       523183    672258.2
------------------------------------------------------------------------------

Does anyone want to interpret the results?

  1. What is the mean flat price for each location (roughly)
  2. Are there any significant differences?
cat(interpretation_price_location)

Mean Centre = 597 721$ 

Mean South  = 425 470$ (p = .038) 

Mean West   = 513 788$ 

Mean East   = 499 728$ 

We can also see that the model as a whole is non-significant with an R^2 around 3%

One problem with this approach is that we’re only using planned contrasts. So we are unable to test the difference between all loactions. We could simply change the refrence group, and re-run the regression:

flats2$location <- relevel(flats$location, ref = "south")

reg_price_location <- lm(flat_price ~ location, data = flats)
preg(reg_price_location)
 
 
 
 Model fit: flat_price 
# Color data frame (class colorDF) 6 x 3:
        │SS      │df   │M.      │M    │R            │R.      
   Model│2.95e+11│    3│F(3, 91)│ 2.05│    R-squared│6.34e-02
Residual│4.36e+12│   91│prob > F│  0.1│adj R-squared│3.25e-02
   Total│4.65e+12│   94│       N│   95│          MSE│2.19e+05

 
 Coefficients: flat_price 
# Color data frame (class colorDF) 6 x 4:
             │ Coefficients│ std.error│ t-value│ p-value│ CI[2.5%]│ CI[97.5%]
  (Intercept)│       597721│     37524│   15.93│  <2e-16│   523183│    672258
locationsouth│      -172350│     82021│   -2.10│  0.0384│  -335275│     -9425
 locationwest│       -83933│     75897│   -1.11│  0.2717│  -234692│     66827
 locationeast│       -97993│     50752│   -1.93│  0.0566│  -198805│      2819

In STATA we can simply use an extension of the i. operator: ib#, where # indicates what variable to use as our base level (i.e., our reference group)

      Source |       SS           df       MS      Number of obs   =        95
-------------+----------------------------------   F(3, 91)        =      2.05
       Model |  2.9488e+11         3  9.8294e+10   Prob > F        =    0.1120
    Residual |  4.3566e+12        91  4.7875e+10   R-squared       =    0.0634
-------------+----------------------------------   Adj R-squared   =    0.0325
       Total |  4.6515e+12        94  4.9484e+10   Root MSE        =    2.2e+05

------------------------------------------------------------------------------
  flat_price |      Coef.   Std. Err.      t    P>|t|     [95% Conf. Interval]
-------------+----------------------------------------------------------------
    location |
     centre  |   172350.2   82021.29     2.10   0.038     9424.993    335275.4
       west  |    88417.5   98344.59     0.90   0.371      -106932      283767
       east  |   74357.26   80542.46     0.92   0.358    -85630.44      234345
             |
       _cons |   425370.4    72934.3     5.83   0.000     280495.3    570245.4
------------------------------------------------------------------------------

Of note we should adjust p-values when performing multiple comparisons, which there are many ways of doing. We will not look into it today.

Boxplots

library(ggplot2)
flats %>% ggplot(mapping = aes(x = location,
                               y = flat_price,
                               colour = location)) +
  geom_boxplot() +
  
  geom_jitter(size = 0.1) +
  
  stat_summary(fun = "mean", 
               geom = "point", 
               colour = "green") +
  
  stat_summary(fun.data = "mean_cl_boot", 
               geom = "errorbar",
               colour = "darkblue",
               width = 0.2) 

NA
NA
NA
NA
NA

Adding Covariates

  1. A covariate is essentially any variable which causes our coefficients to represent adjusted means, as opposed to actual means

Since (unless we add interaction terms) our models are additive, covariates can be both continous and categorical

Example of a Categorical Covariate

R


# Renaming energy-efficiency to make the output a bit more readable
flats2 <- flats %>% rename(e_effic = energy_efficiency)

reg_price_location_energy <- lm(flat_price ~ location + e_effic,
                                data = flats2)
preg(reg_price_location_energy)
 
 
 
 Model fit: flat_price 
# Color data frame (class colorDF) 6 x 3:
        │SS      │df   │M.      │M    │R            │R.      
   Model│5.12e+11│    5│F(5, 76)│ 2.16│    R-squared│1.25e-01
Residual│3.60e+12│   76│prob > F│ 0.07│adj R-squared│6.70e-02
   Total│4.11e+12│   81│       N│   82│          MSE│2.18e+05

 
 Coefficients: flat_price 
# Color data frame (class colorDF) 6 x 6:
               │ Coefficients│ std.error│ t-value│ p-value│ CI[2.5%]│ CI[97.5%]
    (Intercept)│       544392│     99239│   5.486│5.19e-07│   346742│    742043
 locationcentre│       199209│     85100│   2.341│  0.0219│    29717│    368700
   locationwest│        97061│    100220│   0.968│  0.3359│  -102545│    296666
   locationeast│        66112│     81137│   0.815│  0.4177│   -95486│    227711
e_efficmediocre│      -112341│     77756│  -1.445│  0.1526│  -267206│     42524
    e_efficpoor│      -198577│     85725│  -2.316│  0.0232│  -369312│    -27842
      Source |       SS           df       MS      Number of obs   =        82
-------------+----------------------------------   F(5, 76)        =      2.16
       Model |  5.1228e+11         5  1.0246e+11   Prob > F        =    0.0669
    Residual |  3.5993e+12        76  4.7360e+10   R-squared       =    0.1246
-------------+----------------------------------   Adj R-squared   =    0.0670
       Total |  4.1116e+12        81  5.0761e+10   Root MSE        =    2.2e+05

------------------------------------------------------------------------------
  flat_price |      Coef.   Std. Err.      t    P>|t|     [95% Conf. Interval]
-------------+----------------------------------------------------------------
    location |
      south  |  -199208.5   85099.86    -2.34   0.022    -368699.6   -29717.43
       west  |  -102147.8   82903.83    -1.23   0.222      -267265    62969.53
       east  |    -133096   57940.96    -2.30   0.024    -248495.4   -17696.59
             |
energy_eff~y |
   mediocre  |  -112340.8   77756.19    -1.44   0.153    -267205.7    42524.08
       poor  |  -198576.9   85724.61    -2.32   0.023    -369312.3   -27841.56
             |
       _cons |   743600.9   87636.03     8.49   0.000     569058.7    918143.2
------------------------------------------------------------------------------

Example of a Continous Covariate

R

reg_price_location_floor_size <- lm(flat_price ~ location + floor_size,
                                    data = flats)
preg(reg_price_location_floor_size)
 
 
 
 Model fit: flat_price 
# Color data frame (class colorDF) 6 x 3:
        │SS      │df   │M.      │M    │R            │R.      
   Model│3.04e+12│    4│F(4, 90)│42.35│    R-squared│6.53e-01
Residual│1.61e+12│   90│prob > F│6e-20│adj R-squared│6.38e-01
   Total│4.65e+12│   94│       N│   95│          MSE│1.34e+05

 
 Coefficients: flat_price 
# Color data frame (class colorDF) 6 x 5:
              │ Coefficients│ std.error│ t-value│ p-value│ CI[2.5%]│ CI[97.5%]
   (Intercept)│       -16494│     57173│  -0.288│0.773633│  -130079│     97091
locationcentre│       182491│     50204│   3.635│0.000462│    82752│    282230
  locationwest│       103287│     60199│   1.716│0.089646│   -16309│    222883
  locationeast│       136509│     49548│   2.755│0.007101│    38074│    234944
    floor_size│         5295│       428│  12.368│ < 2e-16│     4445│      6146

STATA

      Source |       SS           df       MS      Number of obs   =        95
-------------+----------------------------------   F(4, 90)        =     42.35
       Model |  3.0377e+12         4  7.5942e+11   Prob > F        =    0.0000
    Residual |  1.6138e+12        90  1.7931e+10   R-squared       =    0.6531
-------------+----------------------------------   Adj R-squared   =    0.6376
       Total |  4.6515e+12        94  4.9484e+10   Root MSE        =    1.3e+05

------------------------------------------------------------------------------
  flat_price |      Coef.   Std. Err.      t    P>|t|     [95% Conf. Interval]
-------------+----------------------------------------------------------------
    location |
      south  |  -182490.9   50203.81    -3.64   0.000    -282229.5   -82752.28
       west  |  -79203.74    46450.5    -1.71   0.092    -171485.8    13078.29
       east  |  -45981.88   31343.61    -1.47   0.146    -108251.4    16287.69
             |
  floor_size |   5295.314   428.1549    12.37   0.000     4444.709    6145.918
       _cons |   165996.8   41784.01     3.97   0.000     82985.57      249008
------------------------------------------------------------------------------

Visualizing a dummy-variable regression with a continuous covariate

  1. A dummy-variable regression with a continiuous covariate can in essence be visualized as k (K = number of variable) different linear regressions with the same slope, where the dummy-variable coefficients represent differences in intercepts/constants (i.e., differences controlled for the variable on the x-axis)

R

library(margins)
pred_price_location_size <- margins(reg_price_location_floor_size, 
        at = list(location = c("centre",
                               "south",
                               "west",
                               "east"),
                  floor_size = c(20,220)
        )
)

pred_price_location_size %>% ggplot(mapping = aes(x = floor_size,
                                                  y = fitted, 
                                                  colour = location)) +
  geom_smooth(method = "lm", se = F)

STATA

      Source |       SS           df       MS      Number of obs   =        95
-------------+----------------------------------   F(4, 90)        =     42.35
       Model |  3.0377e+12         4  7.5942e+11   Prob > F        =    0.0000
    Residual |  1.6138e+12        90  1.7931e+10   R-squared       =    0.6531
-------------+----------------------------------   Adj R-squared   =    0.6376
       Total |  4.6515e+12        94  4.9484e+10   Root MSE        =    1.3e+05

------------------------------------------------------------------------------
  flat_price |      Coef.   Std. Err.      t    P>|t|     [95% Conf. Interval]
-------------+----------------------------------------------------------------
    location |
      south  |  -182490.9   50203.81    -3.64   0.000    -282229.5   -82752.28
       west  |  -79203.74    46450.5    -1.71   0.092    -171485.8    13078.29
       east  |  -45981.88   31343.61    -1.47   0.146    -108251.4    16287.69
             |
  floor_size |   5295.314   428.1549    12.37   0.000     4444.709    6145.918
       _cons |   165996.8   41784.01     3.97   0.000     82985.57      249008
------------------------------------------------------------------------------


Adjusted predictions                            Number of obs     =         95
Model VCE    : OLS

Expression   : Linear prediction, predict()

1._at        : location        =           1
               floor_size      =          20

2._at        : location        =           1
               floor_size      =          70

3._at        : location        =           1
               floor_size      =         120

4._at        : location        =           1
               floor_size      =         170

5._at        : location        =           1
               floor_size      =         220

6._at        : location        =           2
               floor_size      =          20

7._at        : location        =           2
               floor_size      =          70

8._at        : location        =           2
               floor_size      =         120

9._at        : location        =           2
               floor_size      =         170

10._at       : location        =           2
               floor_size      =         220

11._at       : location        =           3
               floor_size      =          20

12._at       : location        =           3
               floor_size      =          70

13._at       : location        =           3
               floor_size      =         120

14._at       : location        =           3
               floor_size      =         170

15._at       : location        =           3
               floor_size      =         220

16._at       : location        =           4
               floor_size      =          20

17._at       : location        =           4
               floor_size      =          70

18._at       : location        =           4
               floor_size      =         120

19._at       : location        =           4
               floor_size      =         170

20._at       : location        =           4
               floor_size      =         220

------------------------------------------------------------------------------
             |            Delta-method
             |     Margin   Std. Err.      t    P>|t|     [95% Conf. Interval]
-------------+----------------------------------------------------------------
         _at |
          1  |   271903.1   34948.56     7.78   0.000     202471.6    341334.5
          2  |   536668.7   23489.52    22.85   0.000     490002.7    583334.8
          3  |   801434.4    28261.2    28.36   0.000     745288.6    857580.2
          4  |    1066200   44296.92    24.07   0.000     978196.5     1154204
          5  |    1330966   63579.25    20.93   0.000      1204654     1457277
          6  |   89412.15   52251.76     1.71   0.090    -14395.08    193219.4
          7  |   354177.8   45005.51     7.87   0.000     264766.5    443589.1
          8  |   618943.5    47300.4    13.09   0.000       524973      712914
          9  |   883709.2   58015.03    15.23   0.000     768452.2    998966.2
         10  |    1148475   73557.74    15.61   0.000      1002340     1294610
         11  |   192699.3   48001.31     4.01   0.000     97336.34    288062.3
         12  |     457465   40630.68    11.26   0.000     376745.1    538184.9
         13  |   722230.7   43751.13    16.51   0.000     635311.4    809149.9
         14  |   986996.4   55624.22    17.74   0.000     876489.1     1097504
         15  |    1251762   72045.32    17.37   0.000      1108631     1394893
         16  |   225921.2   30454.41     7.42   0.000     165418.2    286424.2
         17  |   490686.9   20925.63    23.45   0.000     449114.5    532259.3
         18  |   755452.5   29408.76    25.69   0.000     697026.9    813878.2
         19  |    1020218   46994.17    21.71   0.000     926856.1     1113580
         20  |    1284984   66847.67    19.22   0.000      1152179     1417788
------------------------------------------------------------------------------


  Variables that uniquely identify margins: floor_size location

Section 2: Interaction

  1. Interactionterms can be added directly in the regression command/function in both STATA and R
  2. In R we use the ” * ” operator
    1. This automatically adds the relevant variables as normal predictors as well
    2. If we only want the interaction term (without the singular predictors) we can use the ” : ” operator
  3. In STATA ” * ” = “##”, and ” : ” = “#”

Example of an interaction between two continuous variables

reg_price_size_int_year <- lm(flat_price ~ floor_size * year_built, data = flats)
preg(reg_price_size_int_year)
 
 
 
 Model fit: flat_price 
# Color data frame (class colorDF) 6 x 3:
        │SS      │df   │M.      │M    │R            │R.      
   Model│2.79e+12│    3│F(3, 75)│47.95│    R-squared│6.57e-01
Residual│1.45e+12│   75│prob > F│2e-17│adj R-squared│6.44e-01
   Total│4.25e+12│   78│       N│   79│          MSE│1.39e+05

 
 Coefficients: flat_price 
# Color data frame (class colorDF) 6 x 4:
                     │ Coefficients│ std.error│ t-value│ p-value│ CI[2.5%]│ CI[97.5%]
          (Intercept)│    -53097803│  1.44e+07│   -3.70│0.000410│-81694781│ -24500824
           floor_size│       615583│  1.68e+05│    3.67│0.000445│   281824│    949342
           year_built│        26541│  7.16e+03│    3.71│0.000398│    12281│     40800
floor_size:year_built│         -304│  8.35e+01│   -3.64│0.000495│     -471│      -138

STATA

In STATA we recommend that one uses c. or i. to specify, in some instances it can cause problems if they are not specified correctly (e.g., try this code reg flat_price floor_size##year_built)

      Source |       SS           df       MS      Number of obs   =        79
-------------+----------------------------------   F(3, 75)        =     47.95
       Model |  2.7905e+12         3  9.3017e+11   Prob > F        =    0.0000
    Residual |  1.4548e+12        75  1.9397e+10   R-squared       =    0.6573
-------------+----------------------------------   Adj R-squared   =    0.6436
       Total |  4.2453e+12        78  5.4427e+10   Root MSE        =    1.4e+05

------------------------------------------------------------------------------
  flat_price |      Coef.   Std. Err.      t    P>|t|     [95% Conf. Interval]
-------------+----------------------------------------------------------------
  floor_size |   615582.8   167541.2     3.67   0.000     281823.7    949341.9
  year_built |   26540.77   7157.913     3.71   0.000     12281.48    40800.06
             |
          c. |
  floor_size#|
c.year_built |  -304.3031   83.54934    -3.64   0.000    -470.7419   -137.8642
             |
       _cons |  -5.31e+07   1.44e+07    -3.70   0.000    -8.17e+07   -2.45e+07
------------------------------------------------------------------------------

Visualizing interactions between two continuous variables

3D

persp(reg_price_size_int_year, 
      xvar = "floor_size", 
      yvar = "year_built",
      theta = -30,
      phi = 15)
Error: object 'reg_price_size_int_year' not found
library(plotly)

Attaching package: ‘plotly’

The following object is masked from ‘package:ggplot2’:

    last_plot

The following object is masked from ‘package:stats’:

    filter

The following object is masked from ‘package:graphics’:

    layout
# Removing NA's 
flats_NA_removed <- na.omit(flats)

# Creating a grid representing our regression plane
grid_size <- 30
seq_floor_size <- seq(min(flats_NA_removed$floor_size, na.rm = T),
                      max(flats_NA_removed$floor_size, na.rm = T),
                      length.out = grid_size)

seq_year_built <- seq(min(flats_NA_removed$year_built, na.rm = T),
                      max(flats_NA_removed$year_built, na.rm = T),
                      length.out = grid_size)

year_size <- expand.grid(floor_size = seq_floor_size,
                   year_built = seq_year_built)

predicted_price <- matrix(predict(reg_price_size_int_year, 
                                  newdata = year_size),
                          ncol = grid_size, 
                          nrow = grid_size, 
                          byrow = TRUE) 


plot_ly(data = flats_NA_removed,
        type = "scatter3d",
        x = ~floor_size,
        y = ~year_built,
        z = ~flat_price,
        color = ~location,
        size = I(150)) %>%
  add_surface(x = seq_floor_size,
              y = seq_year_built,
              z = predicted_price,
              opacity = .3)
No scatter3d mode specifed:
  Setting the mode to markers
  Read more about this attribute -> https://plotly.com/r/reference/#scatter-mode
No scatter3d mode specifed:
  Setting the mode to markers
  Read more about this attribute -> https://plotly.com/r/reference/#scatter-mode
NA

2D

library(margins)

pred_price_size_int_year <- margins(reg_price_size_int_year,
                                    at = list(floor_size = c(20, 220),
                                              year_built = seq(1930, 2010, 20)
                                              )
                                    )
pred_price_size_int_year <- pred_price_size_int_year %>% 
  mutate(year_built = factor(year_built,
                             levels = seq(1930, 2010, 20),
                             labels = as.character(
                               seq(1930, 2010, 20)
                               )
                             )
         )

pred_price_size_int_year %>% 
  ggplot(mapping = aes(x = floor_size,
                       y = fitted,
                       colour = year_built)) +
  geom_smooth(method = "lm", se = F)

STATA

reg flat_price c.floor_size##c.year_built 
margins , at (floor_size = (20(200)220) year_built = (1930(20)2010))
marginsplot

Example: Interaction between a continuous and a categorical variable

  1. Allowing for interactions between a continuous and categorical variable, can in essence be thought of as four separate regressions with their own intercept and slope.

  2. This is even true when adding another continuous and/or categorical variable, but in that case all interaction terms have to be saturated (which quickly becomes complicated).

  3. In this example we have a continuous variable X1 and two separate dummy variables X2 and X3: \(Y_i = \beta_0 + \beta_1X_{1i} + \beta_2 X_{2i} + \beta_3 X_{3i} + \beta_4 X_{1i} X_{2i} + \beta_5 X_{1i} X_{3i} + \beta_6 X_{2i} + \beta_7 X_{1i} X_{2i} X_{3i}\)

    NB: We could simply use lm(Y ~ X1*X2*X3, data = df) in R, and reg Y X1##X2##X3 in STATA

  4. This would then be the same as running a separate regression for each unique group (i.e., each unique combination of B2 and B3).

R

reg_price_location_int_size <- lm(flat_price ~ location*floor_size, data = flats)
preg(reg_price_location_int_size)
 
 
 
 Model fit: flat_price 
# Color data frame (class colorDF) 6 x 3:
        │SS      │df   │M.      │M    │R            │R.      
   Model│3.08e+12│    7│F(7, 87)│24.34│    R-squared│6.62e-01
Residual│1.57e+12│   87│prob > F│5e-18│adj R-squared│6.35e-01
   Total│4.65e+12│   94│       N│   95│          MSE│1.34e+05

 
 Coefficients: flat_price 
# Color data frame (class colorDF) 6 x 8:
                         │ Coefficients│ std.error│ t-value│ p-value│ CI[2.5%]│ CI[97.5%]
              (Intercept)│       125185│    149184│   0.839│  0.4037│  -171333│    421704
           locationcentre│        36572│    156501│   0.234│  0.8158│  -274491│    347635
             locationwest│      -251538│    243004│  -1.035│  0.3035│  -734535│    231459
             locationeast│         2662│    167061│   0.016│  0.9873│  -329390│    334714
               floor_size│         3597│      1705│   2.110│  0.0378│      208│      6987
locationcentre:floor_size│         1750│      1779│   0.984│  0.3280│    -1786│      5286
  locationwest:floor_size│         4341│      2883│   1.506│  0.1358│    -1390│     10072
  locationeast:floor_size│         1589│      1980│   0.802│  0.4246│    -2347│      5525

STATA

      Source |       SS           df       MS      Number of obs   =        95
-------------+----------------------------------   F(7, 87)        =     24.34
       Model |  3.0793e+12         7  4.3991e+11   Prob > F        =    0.0000
    Residual |  1.5721e+12        87  1.8071e+10   R-squared       =    0.6620
-------------+----------------------------------   Adj R-squared   =    0.6348
       Total |  4.6515e+12        94  4.9484e+10   Root MSE        =    1.3e+05

------------------------------------------------------------------------------
  flat_price |      Coef.   Std. Err.      t    P>|t|     [95% Conf. Interval]
-------------+----------------------------------------------------------------
    location |
      south  |  -36571.84   156501.1    -0.23   0.816    -347634.7      274491
       west  |  -288109.7   197565.6    -1.46   0.148    -680792.6    104573.3
       east  |  -33910.22    88828.6    -0.38   0.704    -210466.7    142646.2
             |
  floor_size |   5347.314   506.5162    10.56   0.000     4340.558    6354.069
             |
    location#|
c.floor_size |
      south  |  -1749.891   1778.903    -0.98   0.328    -5285.654    1785.872
       west  |   2591.292   2379.662     1.09   0.279    -2138.544    7321.128
       east  |  -161.2235   1127.105    -0.14   0.887    -2401.466    2079.019
             |
       _cons |   161757.3   47295.29     3.42   0.001     67752.75    255761.8
------------------------------------------------------------------------------
  1. When interpreting this regression, the intercept of each location is the intercept (B0) + the coefficent for the location.
  2. The slope for floor_size for each location is the slope for floor_size + the slope for location
    1. This is because the interaction term represents the change in slope per 1 unit change
    2. And dummy variables are either 0 or 1.
  3. We can for example see that the highest intercept (i.e., predicted flat_price at floor_size = 0) belongs to centre (161 757), while the lowest belongs to west (161 757 - 288 110 = -126353).
  4. We can also see that the largest slope belongs to west (5347 + 2591 = 7938), while the smallest belongs to south (5347 - 1750 = 3597)

Visualizing interaction between a categorical and a continuous variable

R: The Model

pred_location_int_floor <- margins(reg_price_location_int_size,
                                   at = list(location = c("centre",
                                                          "south",
                                                          "west",
                                                          "east"),
                                             floor_size = c(0,220)
                                             )
                                   )
Warning: A 'at' value for 'floor_size' is outside observed data range (20,228)!

R: Running separate regressions for each location

Here you can see we get the same plot, showing that it indeed is equivalent to running four separate regressions (in terms of your coefficients).

flats %>% ggplot(mapping = aes(x = floor_size,
                               y = flat_price,
                               colour = location)) +
  geom_smooth(method = "lm", se = FALSE, fullrange = T)

STATA

reg flat_price i.location##c.floor_size

margins , at(floor_size = (20(200)220) location = (1(1)4))

marginsplot

reg flat_price i.location##c.floor_size

margins , at(floor_size = (20(200)220) location = (1(1)4))
marginsplot

Exercises

  1. Run a regression with flat price as a dependent variable and energy efficiency as categorical variable

    1. Optional: run the same regression by creating the dummy variables before hand, and by using the built in dummy-variable functionality in the lm() and reg command.
  2. Change the reference group in the regression model

  3. Add a continuous covariate to the regression model

  4. Visualize the regression in a two-dimensional plot.

  5. Run a multiple regression with an interaction between two continuous variables

  6. Interpret the results

  7. Visualize your model in 2D

  8. Run a multiple regression with an interaction between a continuous and a categorical variable

  9. Interpret the results

  10. Visualize your model in 2D

Section 3: Mediation Analysis

  1. In this section we’re going to assess mediation based on Baron and Kenny’s (1968)
  2. First we’re going to go through the original regression approach
  3. Then we’re going to show the adjusted SEM-approach

We’re going to be using the workout dataset

R

step_1 <- lm(calories ~ attract, data = df)
preg(step_1)
 
 
 
 Model fit: calories 
# Color data frame (class colorDF) 6 x 3:
        │SS   │df   │M.       │M    │R            │R.    
   Model│   57│    1│F(1, 202)│23.51│    R-squared│0.1043
Residual│  490│  202│ prob > F│2e-06│adj R-squared│0.0998
   Total│  547│  203│        N│  204│          MSE│1.5571

 
 Coefficients: calories 
# Color data frame (class colorDF) 6 x 2:
           │ Coefficients│ std.error│ t-value│ p-value│ CI[2.5%]│ CI[97.5%]
(Intercept)│         3.08│     0.224│   13.76│ < 2e-16│    2.643│     3.527
    attract│         0.31│     0.064│    4.85│2.48e-06│    0.184│     0.437

STATA

// NB change profile.do
use workout.dta, clear

Regression Approach: Baron and Kenny (1968)

  1. In a mediation analysis we have an independent variable \(X\)

  2. A mediating variable \(M\)

  3. An a dependent variable \(Y\)

  4. In mediation we have the direct effects of \(X\mapsto M\), \(M\mapsto Y\) and the direct relationship \(c\) where \(X \mapsto Y\)

  5. Lastly we have the indirect relationship \(c'\) where \(X \mapsto Y\), while controlling for \(M\)

  6. These relationships are assessed through four steps

    NB: Note that the language implies causation, but that it really requires experimental data to be sure

Steps

  1. Simple regressions assessing \(c\), \(X \mapsto Y\):

    \(Y = \beta_0 + \beta_1 X_{i} + e_i\)

  2. Simple regression assessing \(X\mapsto M\) (effect a):

    \(M = \beta_0 + \beta_1X_{i} +e_i\)

  3. Simple regression assessing \(M\mapsto Y\) (effect b):

    \(Y = \beta_0 + \beta_1 X_{i} + e_i\)

  4. Multiple regression assessing \(c'\):

    \(Y = \beta_0 + \beta_1 X_{i} + \beta_2 M_{i} + e_i\)

Interpreting Steps

  1. For there to be mediation all direct relationships (steps 1-3) must be significant
  2. If one (or multiple) of these are non-significant we usually assume there is no mediating relationship
  3. If steps 1-3 are significant, we proceed to step 4
  4. For there to be mediation, \(M\) still needs to have a significant effect upon \(Y\), when controlling for \(X\)
  5. If \(X\) still has an effect upon \(Y\) (i.e., it is significant) when controlled for \(M\) it suggests partial mediation
  6. If \(X\) no longer has an effect upon \(Y\) (i.e., it is non-significant) when controlled for \(M\) it suggests full mediation

Calculating indirect effect

Delta (difference in \(\beta_1\) between step 1 and 4)

\[ \beta_{indirect} = \beta_{step_1} - \beta_{step4} \]

Sobel product (product of \(\beta\) from \(X\mapsto M\) and \(M\mapsto Y\) )

(i.e., this is the same approach as calculating a correlation matrix/covariance matrix from path analysis, where we multiply the effect of \(X\) on \(M\), with the partial effect of \(M\) on \(Y\))

\[ \beta_{indirect} = \beta_{X\mapsto M} - \beta_{partialM\mapsto Y} \]

Conveniently Sobel = Delta

In R:

Y = calories

X = attract

M = appear

Step 1

step_1 <- lm(calories ~ attract, data = workout)
preg(step_1)
 
 
 
 Model fit: calories 
# Color data frame (class colorDF) 6 x 3:
        │SS   │df   │M.       │M    │R            │R.    
   Model│   57│    1│F(1, 202)│23.51│    R-squared│0.1043
Residual│  490│  202│ prob > F│2e-06│adj R-squared│0.0998
   Total│  547│  203│        N│  204│          MSE│1.5571

 
 Coefficients: calories 
# Color data frame (class colorDF) 6 x 2:
           │ Coefficients│ std.error│ t-value│ p-value│ CI[2.5%]│ CI[97.5%]
(Intercept)│         3.08│     0.224│   13.76│ < 2e-16│    2.643│     3.527
    attract│         0.31│     0.064│    4.85│2.48e-06│    0.184│     0.437
      Source |       SS           df       MS      Number of obs   =       204
-------------+----------------------------------   F(1, 202)       =     23.51
       Model |  57.0014805         1  57.0014805   Prob > F        =    0.0000
    Residual |  489.758323       202  2.42454616   R-squared       =    0.1043
-------------+----------------------------------   Adj R-squared   =    0.0998
       Total |  546.759804       203  2.69339805   Root MSE        =    1.5571

------------------------------------------------------------------------------
    calories |      Coef.   Std. Err.      t    P>|t|     [95% Conf. Interval]
-------------+----------------------------------------------------------------
     attract |   .3104855   .0640344     4.85   0.000     .1842239    .4367471
       _cons |   3.084593   .2241653    13.76   0.000     2.642589    3.526597
------------------------------------------------------------------------------

We can see that the effect of appear on calories is significant

Step 2

step_2 <- lm(appear ~ attract, data = workout)
preg(step_2)
 
 
 
 Model fit: appear 
# Color data frame (class colorDF) 6 x 3:
        │SS   │df   │M.       │M     │R            │R.   
   Model│  421│    1│F(1, 201)│587.74│    R-squared│0.745
Residual│  144│  201│ prob > F│ 1e-61│adj R-squared│0.744
   Total│  565│  202│        N│   203│          MSE│0.846

 
 Coefficients: appear 
# Color data frame (class colorDF) 6 x 2:
           │ Coefficients│ std.error│ t-value│ p-value│ CI[2.5%]│ CI[97.5%]
(Intercept)│        0.783│     0.122│    6.42│9.45e-10│    0.543│     1.024
    attract│        0.847│     0.035│   24.24│ < 2e-16│    0.778│     0.915
      Source |       SS           df       MS      Number of obs   =       203
-------------+----------------------------------   F(1, 201)       =    587.74
       Model |  421.035858         1  421.035858   Prob > F        =    0.0000
    Residual |  143.988773       201  .716362054   R-squared       =    0.7452
-------------+----------------------------------   Adj R-squared   =    0.7439
       Total |  565.024631       202  2.79715164   Root MSE        =    .84638

------------------------------------------------------------------------------
      appear |      Coef.   Std. Err.      t    P>|t|     [95% Conf. Interval]
-------------+----------------------------------------------------------------
     attract |   .8465505   .0349188    24.24   0.000     .7776963    .9154047
       _cons |   .7831785   .1219268     6.42   0.000     .5427588    1.023598
------------------------------------------------------------------------------

We also see that the effect of attract on appear is significant

Step 3

step_3 <- lm(calories ~ appear, data = workout)
preg(step_3)
 
 
 
 Model fit: calories 
# Color data frame (class colorDF) 6 x 3:
        │SS   │df   │M.       │M    │R            │R.   
   Model│ 93.8│    1│F(1, 201)│41.97│    R-squared│0.173
Residual│449.1│  201│ prob > F│7e-10│adj R-squared│0.169
   Total│542.9│  202│        N│  203│          MSE│1.495

 
 Coefficients: calories 
# Color data frame (class colorDF) 6 x 2:
           │ Coefficients│ std.error│ t-value│ p-value│ CI[2.5%]│ CI[97.5%]
(Intercept)│        2.654│     0.236│   11.24│  <2e-16│    2.188│     3.120
     appear│        0.407│     0.063│    6.48│   7e-10│    0.283│     0.531
      Source |       SS           df       MS      Number of obs   =       203
-------------+----------------------------------   F(1, 201)       =     41.97
       Model |  93.7686694         1  93.7686694   Prob > F        =    0.0000
    Residual |  449.108178       201  2.23436904   R-squared       =    0.1727
-------------+----------------------------------   Adj R-squared   =    0.1686
       Total |  542.876847       202  2.68750915   Root MSE        =    1.4948

------------------------------------------------------------------------------
    calories |      Coef.   Std. Err.      t    P>|t|     [95% Conf. Interval]
-------------+----------------------------------------------------------------
      appear |   .4073758   .0628845     6.48   0.000     .2833778    .5313738
       _cons |   2.654002     .23616    11.24   0.000     2.188333    3.119671
------------------------------------------------------------------------------

Since appear also has a significant effect upon appear we can move on to step 4

Step 4

step_4 <- lm(calories ~ attract + appear, data = workout)
preg(step_4)
 
 
 
 Model fit: calories 
# Color data frame (class colorDF) 6 x 3:
        │SS   │df   │M.       │M    │R            │R.   
   Model│ 97.3│    2│F(2, 200)│21.83│    R-squared│0.179
Residual│445.6│  200│ prob > F│3e-09│adj R-squared│0.171
   Total│542.9│  202│        N│  203│          MSE│1.493

 
 Coefficients: calories 
# Color data frame (class colorDF) 6 x 3:
           │ Coefficients│ std.error│ t-value│ p-value│ CI[2.5%]│ CI[97.5%]
(Intercept)│        2.667│     0.236│   11.30│ < 2e-16│    2.202│     3.133
    attract│       -0.153│     0.122│   -1.25│   0.212│   -0.393│     0.088
     appear│        0.542│     0.124│    4.36│2.12e-05│    0.296│     0.787
      Source |       SS           df       MS      Number of obs   =       203
-------------+----------------------------------   F(2, 200)       =     21.83
       Model |  97.2580367         2  48.6290183   Prob > F        =    0.0000
    Residual |  445.618811       200  2.22809405   R-squared       =    0.1792
-------------+----------------------------------   Adj R-squared   =    0.1709
       Total |  542.876847       202  2.68750915   Root MSE        =    1.4927

------------------------------------------------------------------------------
    calories |      Coef.   Std. Err.      t    P>|t|     [95% Conf. Interval]
-------------+----------------------------------------------------------------
     attract |  -.1526638   .1219915    -1.25   0.212    -.3932183    .0878907
      appear |   .5417558   .1243949     4.36   0.000     .2964621    .7870496
       _cons |   2.667387   .2360706    11.30   0.000     2.201881    3.132894
------------------------------------------------------------------------------

M is significant which points towards mediation. Since attract has become non-significant it suggests full mediation.

Indirect effects (this is only to show the computation)

NB: There is a popular package for this in R, but it requires an older version of R

Delta

delta <- step_1$coefficients[2] - step_4$coefficients[2]
delta
  attract 
0.4631493 

Sobel

alpha <- step_2$coefficients[2] 
beta <- step_4$coefficients[3]
sobel <- alpha * beta
sobel
  attract 
0.4586237 

We can use sobels effect to calculate its std.error, which can give us a p-statistic

std.error_alpha <- summary(step_2)[["coefficients"]][2,2]
std.error_beta <- summary(step_4)[["coefficients"]][3,2]

sobel_z <- sqrt(alpha^2*std.error_beta^2 + 
                  beta^2*std.error_alpha^2 +
                  std.error_alpha^2*std.error_beta^2) 
sobel_z
  attract 
0.1070804 
CI_low = sobel - sobel_z*1.96
CI_high = sobel + sobel_z*1.96
cat("CI_low =", CI_low, "CI_high =", CI_high)
CI_low = 0.2487462 CI_high = 0.6685012

SEM Approach

  1. There are multiple advantages of using the SEM-approach, as opposed to the regression approach
  2. When we only use observed variables we should get the same coefficents but we will get a bit larger std.errors (around < .001 with N > 200)
  3. The biggest advantage is that it is simpler, since you simply need a single model
  4. It also allows you to use latent variables, not only observed variables
# install.packages("lavaan", dependencies = T)
# devtools::install_github("ihrke/rmedsem")

library(rmedsem)
library(lavaan)
This is lavaan 0.6-15
lavaan is FREE software! Please report any bugs.
// net install github, from("https://haghish.github.io/github/")
// github install mmoglu/medsem

R: Lavaan Syntax

  1. Predict: ~ (e.g., Y ~ X)

  2. Indication: =~ (Latent Variable ~ Meausured/Observed Variable

  3. ~~ covariance (e.g., X ~~ X)

  4. ~1 intercept or mean (e.g., X ~ 1 estimates the mean of variable X)

  5. 1* fixes parameter/loading to one (useful single item constructs)

  6. NA* frees parameter or loading (useful to override default marker method, (e.g., f =~ NA*q)

  7. a* labels the parameter ‘a’, used for model constraints (e.g., f =~ a*q)


model <- "
    appear ~ attract
    calories ~ attract + appear
"
sem_1 <- sem(model, data = workout)
summary(sem_1)
lavaan 0.6.15 ended normally after 1 iteration

  Estimator                                         ML
  Optimization method                           NLMINB
  Number of model parameters                         5

                                                  Used       Total
  Number of observations                           203         246

Model Test User Model:
                                                      
  Test statistic                                 0.000
  Degrees of freedom                                 0

Parameter Estimates:

  Standard errors                             Standard
  Information                                 Expected
  Information saturated (h1) model          Structured

Regressions:
                   Estimate  Std.Err  z-value  P(>|z|)
  appear ~                                            
    attract           0.847    0.035   24.364    0.000
  calories ~                                          
    attract          -0.153    0.121   -1.261    0.207
    appear            0.542    0.123    4.388    0.000

Variances:
                   Estimate  Std.Err  z-value  P(>|z|)
   .appear            0.709    0.070   10.075    0.000
   .calories          2.195    0.218   10.075    0.000

STATA: SEM syntax

  1. The Syntax is quite similar in STATA, but its a bit simpler
  2. “+” is substiduted with ” ” (“spacebar”) and both “=~” and ” ~” ar substituted with “->” (“<-” also works)
  3. medsem, indep(varname) med(varname) dep(varname) [mcreps(number) stand zlc rit rid]
(43 observations with missing values excluded)

Endogenous variables

Observed:  calories appear

Exogenous variables

Observed:  attract

Fitting target model:

Iteration 0:   log likelihood = -1016.9388  
Iteration 1:   log likelihood = -1016.9388  

Structural equation model                       Number of obs     =        203
Estimation method  = ml
Log likelihood     = -1016.9388

------------------------------------------------------------------------------
             |                 OIM
             |      Coef.   Std. Err.      z    P>|z|     [95% Conf. Interval]
-------------+----------------------------------------------------------------
Structural   |
  calories   |
      appear |   .5417558   .1234723     4.39   0.000     .2997546     .783757
     attract |  -.1526638   .1210867    -1.26   0.207    -.3899894    .0846618
       _cons |   2.667387   .2343198    11.38   0.000     2.208129    3.126646
  -----------+----------------------------------------------------------------
  appear     |
     attract |   .8465505   .0347464    24.36   0.000     .7784488    .9146522
       _cons |   .7831785   .1213247     6.46   0.000     .5453865    1.020971
-------------+----------------------------------------------------------------
var(e.calo~s)|   2.195167   .2178886                      1.807085     2.66659
var(e.appear)|   .7093043   .0704044                      .5839071    .8616312
------------------------------------------------------------------------------
LR test of model vs. saturated: chi2(0)   =      0.00, Prob > chi2 =      .


Structural equation model                       Number of obs     =        203
Estimation method  = ml
Log likelihood     = -1016.9388

------------------------------------------------------------------------------
             |                 OIM
Standardized |      Coef.   Std. Err.      z    P>|z|     [95% Conf. Interval]
-------------+----------------------------------------------------------------
Structural   |
  calories   |
      appear |   .5526964   .1197077     4.62   0.000     .3180737    .7873191
     attract |  -.1588152   .1253989    -1.27   0.205    -.4045925    .0869621
       _cons |   1.631111   .1948458     8.37   0.000      1.24922    2.013001
  -----------+----------------------------------------------------------------
  appear     |
     attract |   .8632287   .0141675    60.93   0.000      .835461    .8909964
       _cons |   .4694346   .0857522     5.47   0.000     .3013634    .6375058
-------------+----------------------------------------------------------------
var(e.calo~s)|    .820847   .0480668                      .7318429    .9206754
var(e.appear)|   .2548363   .0244595                      .2111358    .3075818
------------------------------------------------------------------------------
LR test of model vs. saturated: chi2(0)   =      0.00, Prob > chi2 =      .

Using the medsem package

Adjusted Baron and Kenny’s approach (default)

  1. If both or one of the X->M and M->Y coefficients is not significant, there is no mediation

  2. When both of the X->M and M->Y coefficients are significant, there is “some” mediation

    1. If the Sobel’s z-test is significant and the X->Y coefficient is not significant, then there is complete mediation

    2. If both the Sobel’s z-test and the X->Y coefficients are significant, then there is partial mediation

    3. If the Sobel’s z-test is not significant but the X->Y coefficient is significant, then there is partial mediation

    4. If neither Sobel’s z-test nor the X->Y coefficient are significant, then there is partial mediation

med_1 <- rmedsem(sem_1, 
        indep = "attract", 
        med = "appear", 
        dep = "calories",
        approach = c("bk", "zlc")) 
med_1
Significance testing of indirect effect (unstandardized)
Mediation effect: 'attract' -> 'appear' -> 'calories'

Baron and Kenny approach to testing mediation

Zhao, Lynch & Chen's approach to testing mediation
  STEP 1 - 'attract:calories' (X -> Y) with B=-0.153 and p=0.207
            As the Monte Carlo test above is significant and STEP 1 is not
            significant there indirect-only mediation (full mediation).

Effect sizes
   RIT = (Indirect effect / Total effect)
         (0.459/0.306) = 1.499
         Meaning that about 150% of the effect of 'attract'
         on 'calories' is mediated by 'appear'
   RID = (Indirect effect / Direct effect)
         (0.459/0.153) = 3.004
         That is, the mediated effect is about 3.0 times as
         large as the direct effect of 'attract' on 'calories'
(43 observations with missing values excluded)

Endogenous variables

Observed:  calories appear

Exogenous variables

Observed:  attract

Fitting target model:

Iteration 0:   log likelihood = -1016.9388  
Iteration 1:   log likelihood = -1016.9388  

Structural equation model                       Number of obs     =        203
Estimation method  = ml
Log likelihood     = -1016.9388

------------------------------------------------------------------------------
             |                 OIM
             |      Coef.   Std. Err.      z    P>|z|     [95% Conf. Interval]
-------------+----------------------------------------------------------------
Structural   |
  calories   |
      appear |   .5417558   .1234723     4.39   0.000     .2997546     .783757
     attract |  -.1526638   .1210867    -1.26   0.207    -.3899894    .0846618
       _cons |   2.667387   .2343198    11.38   0.000     2.208129    3.126646
  -----------+----------------------------------------------------------------
  appear     |
     attract |   .8465505   .0347464    24.36   0.000     .7784488    .9146522
       _cons |   .7831785   .1213247     6.46   0.000     .5453865    1.020971
-------------+----------------------------------------------------------------
var(e.calo~s)|   2.195167   .2178886                      1.807085     2.66659
var(e.appear)|   .7093043   .0704044                      .5839071    .8616312
------------------------------------------------------------------------------
LR test of model vs. saturated: chi2(0)   =      0.00, Prob > chi2 =      .


  Significance testing of indirect effect (unstandardised)
+--------------------------------------------------------------------------+
  Estimates          |     Delta       |     Sobel       |  Monte Carlo
|--------------------------------------------------------------------------|
  Indirect effect    |     0.459       |     0.459       |     0.466

  Std. Err.          |     0.106       |     0.106       |     0.113

  z-value            |     4.318       |     4.318       |     4.138

  p-value            |     0.000       |     0.000       |     0.000

  Conf. Interval     | 0.250 , 0.667   | 0.250 , 0.667   | 0.276 , 0.686
|--------------------------------------------------------------------------|

  Baron and Kenny approach to testing mediation
  STEP 1 - appear:attract (X -> M) with B=0.847 and p=0.000
  STEP 2 - calories:appear (M -> Y) with B=0.542 and p=0.000
  STEP 3 - calories:attract (X -> Y) with B=-0.153 and p=0.207
           As STEP 1, STEP 2 and the Sobel's test above are significant 
           and STEP 3 is not significant the mediation is complete!
+--------------------------------------------------------------------------+
  Note: to read more about this package help medsem
#install.packages("tidySEM")
library(tidySEM)
graph_sem(sem_1)

Exercises

  1. Use the regression approach to test the relationship between one independent, one mediating and one dependent variable
  2. Use the SEM approach to test the same model
  3. Interpret the results? (Is it no-, some- or full mediation?)
  4. Try to add some extra variables to your model using the SEM approach (tip: the SEM model is the only thing that changes, the medsem variables are the same)
  5. Try adding an extra mediating relationship in your model (tip: now you have to run two medsem commands, one to test each mediation)
  6. Try to create a SEM model with three latent variables: one independent, one mediating and one dependent latent variables
    1. tip: use the =~ operator in R,
    2. In STATA use either -> or <-, but remember that observed variables (in traditional SEM), are functions of your latent variable not the other way around (i.e., it is akin to multiple simple regressions, not a single multiple regression).

Appendix

Appendix: Interpretation (only used to call via cat())

LS0tDQp0aXRsZTogIkR1bW15X01vZGVyYXRpb25fYW5kX01lZGlhdGlvbiINCm91dHB1dDogaHRtbF9ub3RlYm9vaw0KLS0tDQoNCmBgYHtyfQ0KbGlicmFyeShwcHJpbnQpDQpsaWJyYXJ5KGhhdmVuKQ0KbGlicmFyeShTdGF0YW1hcmtkb3duKQ0KbGlicmFyeShkcGx5cikNCmBgYA0KDQojIyBTZWN0aW9uIDE6IER1bW15IFZhcmlhYmxlIFJlZ3Jlc3Npb24NCg0KYGBge3J9DQpzZXR3ZCgiQzovVXNlcnMvc2x1cHAvT25lRHJpdmUvU2tyaXZlYm9yZC9OVE5VL01laG1ldC9QU1k4MDAzL0R1bW15X21vZGVyYXRpb25fYW5kX21lZGlhdGlvbiIpDQpmbGF0cyA8LSByZWFkUkRTKCJmbGF0cy5yZHMiKQ0KDQpgYGANCg0KYGBge3N0YXRhfQ0KY2QgIkM6XFVzZXJzXHNsdXBwXE9uZURyaXZlXFNrcml2ZWJvcmRcTlROVVxNZWhtZXRcUFNZODAwM1xEdW1teV9tb2RlcmF0aW9uX2FuZF9tZWRpYXRpb24iDQp1c2UgZmxhdHMuZHRhDQpgYGANCg0KIyMjIENvbXBhcmluZyBNZWFucw0KDQoxLiAgSWYgd2UncmUgb25seSB1c2luZyBhIHNpbmdsZSBjYXRlZ29yaWNhbCB2YXJpYWJsZSBpbiBvdXIgcmVncmVzc2lvbiBpdCBpcyBha2luIHRvIGEgdC10ZXN0IG9yIGEgb25lLXdheSBBTk9WQQ0KMi4gIFdoaWxlIHdlIGNhbiBjcmVhdGUgZHVtbXkgdmFyaWFibGVzIGluIG91ciBkYXRhc2V0LCBib3RoIFNUQVRBIGFuZCBSIGhhdmUgYnVpbHQgaW4gd2F5cyBvZiBoYW5kbGluZyBjYXRlZ29yaWNhbCB2YXJpYWJsZXMgdGhlaXIgcmVncmVzc2lvbiBjb21tYW5kL2Z1bmN0aW9uLg0KMy4gIEZvciB0aGlzIHRvIHdvcmsgaXQgaXMgaW1wb3J0YW50IHRoYXQgb3VyIHZhcmlhYmxlIGlzIGNvZGVkIGNvcnJlY3RseSAoaS5lLiwgYXMgYSBmYWN0b3IpLCBhbmQgaXQgc2hvdWxkIGFsc28gaGF2ZSBsYWJlbGVkIHZhbHVlcw0KNC4gIExldHMgc2F5IHdlIHdhbnQgdG8gY29tcGFyZSBtZWFuLXByaWNlcyBmb3IgZmxhdHMgYXQgZGlmZmVyZW50IGxvY2F0aW9ucw0KDQojIyMjIExhYmVsaW5nIFZhbHVlcw0KDQoqKlIqKg0KDQpgYGB7cn0NCiMgTkIgdGhlIHZhcmlhYmxlIGlzIGFscmVhZHkgY29kZWQgYXMgYSBmYWN0b3IsIHNvIHRoaXMgaXMgb25seSB0byBzaG93IGhvdyBpdHMgZG9uZSANCiMgU08gRE8gTk9UIFJVTi9PVkVSV1JJVEUgT1JJR0lOQUwgREFUQVNFVA0KZmxhdHMyIDwtIGZsYXRzICU+JSBtdXRhdGUobG9jYXRpb24gPSBmYWN0b3IobG9jYXRpb24sDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKDEsIDIsIDMsIDQpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiY2VudHJlIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgInNvdXRoIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIndlc3QiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiZWFzdCIpKSkNCmBgYA0KDQoqKlNUQVRBKioNCg0KYGBge3N0YXRhfQ0KLy8gQ3JlYXRpbmcgdmFyaWFibGUgd2l0aCBsYWJlbHMNCmxhYmVsIGRlZmluZSBsYWJlbHNfbG9jYXRpb24gMSAiY2VudHJlIiAyICJzb3V0aCIgMyAid2VzdCIgNCAiZWFzdCINCg0KLy8gQXBwbHlpbmcgTGFiZWxzIHRvIGxvY2F0aW9uIA0KbGFiZWwgdmFsdWVzIGxvY2F0aW9uIGxhYmVsc19sb2NhdGlvbiANCg0KY29kZWJvb2sgbG9jYXRpb24NCmBgYA0KDQojIyMjIFJlZ3Jlc3Npb246IENvbXBhcmluZyBNZWFucyBMb2NhdGlvbg0KDQpJZiBvdXIgdmFyaWFibGUgaXMgY29kZWQgY29ycmVjdGx5IChhcyBhIGZhY3Rvcikgd2UgY2FuIHNlZSB0aGF0IFIgYXV0b21hdGljYWxseSB0cmVhdHMgaXQgYXMgYSAob3IgcmF0aGVyIG11dGlwbGUpIGR1bW15IHZhcmlhYmxlKHMpDQoNCmBgYHtyfQ0KcmVnX3ByaWNlX2xvY2F0aW9uIDwtIGxtKGZsYXRfcHJpY2UgfiBsb2NhdGlvbiwgZGF0YSA9IGZsYXRzKQ0KcHJlZyhyZWdfcHJpY2VfbG9jYXRpb24pDQpgYGANCg0KSW4gU1RBVEEgaXQgaXMgbm90IHRoYXQgc2ltcGxlDQoNCmBgYHtzdGF0YX0NCnJlZyBmbGF0X3ByaWNlIGxvY2F0aW9uDQpgYGANCg0KSW4gU1RBVEEgd2UgbmVlZCB0byB1c2UgYSBpLiBpbiBmcm9udCAoTGlrZXdpc2Ugd2UgY2FuIGZvcmNlIGEgY2F0ZWdvcmljYWwgdmFyaWFibGUgYXMgY29udGludW91cyB1c2luZyBjLikNCg0KYGBge3N0YXRhfQ0KcmVnIGZsYXRfcHJpY2UgaS5sb2NhdGlvbg0KYGBgDQoNClRoaXMgd29ya3MgZXZlbiBpZiBvdXIgdmFyaWFibGUgbGFja3MgbGFiZWxzDQoNCmBgYHtzdGF0YX0NCi8vIHJlbW92aW5nIGxhYmVscyBmcm9tIGxvY2F0aW9uDQpsYWJlbCB2YWx1ZXMgbG9jYXRpb24gLg0KDQovL3JlZ3Jlc3Npb24NCnJlZyBmbGF0X3ByaWNlIGkubG9jYXRpb24NCmBgYA0KDQojIyMjICoqRG9lcyBhbnlvbmUgd2FudCB0byBpbnRlcnByZXQgdGhlIHJlc3VsdHM/KioNCg0KMS4gIFdoYXQgaXMgdGhlIG1lYW4gZmxhdCBwcmljZSBmb3IgZWFjaCBsb2NhdGlvbiAocm91Z2hseSkNCjIuICBBcmUgdGhlcmUgYW55IHNpZ25pZmljYW50IGRpZmZlcmVuY2VzPw0KDQpgYGB7cn0NCmNhdChpbnRlcnByZXRhdGlvbl9wcmljZV9sb2NhdGlvbikNCmBgYA0KDQpPbmUgcHJvYmxlbSB3aXRoIHRoaXMgYXBwcm9hY2ggaXMgdGhhdCB3ZSdyZSBvbmx5IHVzaW5nIHBsYW5uZWQgY29udHJhc3RzLiBTbyB3ZSBhcmUgdW5hYmxlIHRvIHRlc3QgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiBhbGwgbG9hY3Rpb25zLiBXZSBjb3VsZCBzaW1wbHkgY2hhbmdlIHRoZSByZWZyZW5jZSBncm91cCwgYW5kIHJlLXJ1biB0aGUgcmVncmVzc2lvbjoNCg0KYGBge3J9DQpmbGF0czIkbG9jYXRpb24gPC0gcmVsZXZlbChmbGF0cyRsb2NhdGlvbiwgcmVmID0gInNvdXRoIikNCg0KcmVnX3ByaWNlX2xvY2F0aW9uIDwtIGxtKGZsYXRfcHJpY2UgfiBsb2NhdGlvbiwgZGF0YSA9IGZsYXRzKQ0KcHJlZyhyZWdfcHJpY2VfbG9jYXRpb24pDQoNCmBgYA0KDQpJbiBTVEFUQSB3ZSBjYW4gc2ltcGx5IHVzZSBhbiBleHRlbnNpb24gb2YgdGhlIGkuIG9wZXJhdG9yOiBpYiMsIHdoZXJlIFwjIGluZGljYXRlcyB3aGF0IHZhcmlhYmxlIHRvIHVzZSBhcyBvdXIgYmFzZSBsZXZlbCAoaS5lLiwgb3VyIHJlZmVyZW5jZSBncm91cCkNCg0KYGBge3N0YXRhfQ0KcmVnIGZsYXRfcHJpY2UgaWIyLmxvY2F0aW9uDQpgYGANCg0KT2Ygbm90ZSB3ZSBzaG91bGQgYWRqdXN0IHAtdmFsdWVzIHdoZW4gcGVyZm9ybWluZyBtdWx0aXBsZSBjb21wYXJpc29ucywgd2hpY2ggdGhlcmUgYXJlIG1hbnkgd2F5cyBvZiBkb2luZy4gV2Ugd2lsbCBub3QgbG9vayBpbnRvIGl0IHRvZGF5Lg0KDQojIyMgQm94cGxvdHMNCg0KYGBge3J9DQpsaWJyYXJ5KGdncGxvdDIpDQpmbGF0cyAlPiUgZ2dwbG90KG1hcHBpbmcgPSBhZXMoeCA9IGxvY2F0aW9uLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHkgPSBmbGF0X3ByaWNlLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG91ciA9IGxvY2F0aW9uKSkgKw0KICBnZW9tX2JveHBsb3QoKSArDQogIA0KICBnZW9tX2ppdHRlcihzaXplID0gMC4xKSArDQogIA0KICBzdGF0X3N1bW1hcnkoZnVuID0gIm1lYW4iLCANCiAgICAgICAgICAgICAgIGdlb20gPSAicG9pbnQiLCANCiAgICAgICAgICAgICAgIGNvbG91ciA9ICJncmVlbiIpICsNCiAgDQogIHN0YXRfc3VtbWFyeShmdW4uZGF0YSA9ICJtZWFuX2NsX2Jvb3QiLCANCiAgICAgICAgICAgICAgIGdlb20gPSAiZXJyb3JiYXIiLA0KICAgICAgICAgICAgICAgY29sb3VyID0gImRhcmtibHVlIiwNCiAgICAgICAgICAgICAgIHdpZHRoID0gMC4yKSANCiAgDQoNCg0KICANCmBgYA0KDQpgYGB7c3RhdGF9DQpncmFwaCBib3ggZmxhdF9wcmljZSwgb3Zlcihsb2NhdGlvbikNCmBgYA0KDQohW10oaW1hZ2VzL1NramVybWJpbGRlJTIwMjAyMy0wNi0wOCUyMDEzMDA0Mi5wbmcpe3dpZHRoPSI5NjkifQ0KDQojIyMgQWRkaW5nIENvdmFyaWF0ZXMNCg0KMS4gIEEgY292YXJpYXRlIGlzIGVzc2VudGlhbGx5IGFueSB2YXJpYWJsZSB3aGljaCBjYXVzZXMgb3VyIGNvZWZmaWNpZW50cyB0byByZXByZXNlbnQgYWRqdXN0ZWQgbWVhbnMsIGFzIG9wcG9zZWQgdG8gYWN0dWFsIG1lYW5zDQoNClNpbmNlICh1bmxlc3Mgd2UgYWRkIGludGVyYWN0aW9uIHRlcm1zKSBvdXIgbW9kZWxzIGFyZSBhZGRpdGl2ZSwgY292YXJpYXRlcyBjYW4gYmUgYm90aCBjb250aW5vdXMgYW5kIGNhdGVnb3JpY2FsDQoNCiMjIyMgRXhhbXBsZSBvZiBhIENhdGVnb3JpY2FsIENvdmFyaWF0ZQ0KDQoqKlIqKg0KDQpgYGB7cn0NCg0KIyBSZW5hbWluZyBlbmVyZ3ktZWZmaWNpZW5jeSB0byBtYWtlIHRoZSBvdXRwdXQgYSBiaXQgbW9yZSByZWFkYWJsZQ0KZmxhdHMyIDwtIGZsYXRzICU+JSByZW5hbWUoZV9lZmZpYyA9IGVuZXJneV9lZmZpY2llbmN5KQ0KDQpyZWdfcHJpY2VfbG9jYXRpb25fZW5lcmd5IDwtIGxtKGZsYXRfcHJpY2UgfiBsb2NhdGlvbiArIGVfZWZmaWMsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBmbGF0czIpDQpwcmVnKHJlZ19wcmljZV9sb2NhdGlvbl9lbmVyZ3kpDQpgYGANCg0KYGBge3N0YXRhfQ0KcmVnIGZsYXRfcHJpY2UgaS5sb2NhdGlvbiBpLmVuZXJneV9lZmZpY2llbmN5DQpgYGANCg0KIyMjIyBFeGFtcGxlIG9mIGEgQ29udGlub3VzIENvdmFyaWF0ZQ0KDQoqKlIqKg0KDQpgYGB7cn0NCnJlZ19wcmljZV9sb2NhdGlvbl9mbG9vcl9zaXplIDwtIGxtKGZsYXRfcHJpY2UgfiBsb2NhdGlvbiArIGZsb29yX3NpemUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gZmxhdHMpDQpwcmVnKHJlZ19wcmljZV9sb2NhdGlvbl9mbG9vcl9zaXplKQ0KYGBgDQoNCioqU1RBVEEqKg0KDQpgYGB7c3RhdGF9DQpyZWcgZmxhdF9wcmljZSBpLmxvY2F0aW9uIGZsb29yX3NpemUNCmBgYA0KDQojIyMgVmlzdWFsaXppbmcgYSBkdW1teS12YXJpYWJsZSByZWdyZXNzaW9uIHdpdGggYSBjb250aW51b3VzIGNvdmFyaWF0ZQ0KDQoxLiAgQSBkdW1teS12YXJpYWJsZSByZWdyZXNzaW9uIHdpdGggYSBjb250aW5pdW91cyBjb3ZhcmlhdGUgY2FuIGluIGVzc2VuY2UgYmUgdmlzdWFsaXplZCBhcyBrIChLID0gbnVtYmVyIG9mIHZhcmlhYmxlKSBkaWZmZXJlbnQgbGluZWFyIHJlZ3Jlc3Npb25zIHdpdGggdGhlIHNhbWUgc2xvcGUsIHdoZXJlIHRoZSBkdW1teS12YXJpYWJsZSBjb2VmZmljaWVudHMgcmVwcmVzZW50IGRpZmZlcmVuY2VzIGluIGludGVyY2VwdHMvY29uc3RhbnRzIChpLmUuLCBkaWZmZXJlbmNlcyBjb250cm9sbGVkIGZvciB0aGUgdmFyaWFibGUgb24gdGhlIHgtYXhpcykNCg0KKipSKioNCg0KYGBge3J9DQpsaWJyYXJ5KG1hcmdpbnMpDQpwcmVkX3ByaWNlX2xvY2F0aW9uX3NpemUgPC0gbWFyZ2lucyhyZWdfcHJpY2VfbG9jYXRpb25fZmxvb3Jfc2l6ZSwgDQogICAgICAgIGF0ID0gbGlzdChsb2NhdGlvbiA9IGMoImNlbnRyZSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgInNvdXRoIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAid2VzdCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgImVhc3QiKSwNCiAgICAgICAgICAgICAgICAgIGZsb29yX3NpemUgPSBjKDIwLDIyMCkNCiAgICAgICAgKQ0KKQ0KDQpwcmVkX3ByaWNlX2xvY2F0aW9uX3NpemUgJT4lIGdncGxvdChtYXBwaW5nID0gYWVzKHggPSBmbG9vcl9zaXplLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB5ID0gZml0dGVkLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb3VyID0gbG9jYXRpb24pKSArDQogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gRikNCmBgYA0KDQoqKlNUQVRBKioNCg0KYGBge3N0YXRhfQ0KcmVnIGZsYXRfcHJpY2UgaS5sb2NhdGlvbiBmbG9vcl9zaXplDQptYXJnaW5zICwgYXQoZmxvb3Jfc2l6ZSA9ICgyMCg1MCkyMjApIGxvY2F0aW9uID0gKDEoMSk0KSkNCm1hcmdpbnNwbG90DQpgYGANCg0KIVtdKGltYWdlcy9Ta2plcm1iaWxkZSUyMDIwMjMtMDYtMDglMjAxNDEyMzgucG5nKXt3aWR0aD0iNzE1In0NCg0KIyMgU2VjdGlvbiAyOiBJbnRlcmFjdGlvbg0KDQoxLiAgSW50ZXJhY3Rpb250ZXJtcyBjYW4gYmUgYWRkZWQgZGlyZWN0bHkgaW4gdGhlIHJlZ3Jlc3Npb24gY29tbWFuZC9mdW5jdGlvbiBpbiBib3RoIFNUQVRBIGFuZCBSDQoyLiAgSW4gUiB3ZSB1c2UgdGhlICIgXCogIiBvcGVyYXRvcg0KICAgIDEuICBUaGlzIGF1dG9tYXRpY2FsbHkgYWRkcyB0aGUgcmVsZXZhbnQgdmFyaWFibGVzIGFzIG5vcm1hbCBwcmVkaWN0b3JzIGFzIHdlbGwNCiAgICAyLiAgSWYgd2Ugb25seSB3YW50IHRoZSBpbnRlcmFjdGlvbiB0ZXJtICh3aXRob3V0IHRoZSBzaW5ndWxhciBwcmVkaWN0b3JzKSB3ZSBjYW4gdXNlIHRoZSAiIDogIiBvcGVyYXRvcg0KMy4gIEluIFNUQVRBICIgXCogIiA9ICJcIyMiLCBhbmQgIiA6ICIgPSAiXCMiDQoNCiMjIyBFeGFtcGxlIG9mIGFuIGludGVyYWN0aW9uIGJldHdlZW4gdHdvIGNvbnRpbnVvdXMgdmFyaWFibGVzDQoNCmBgYHtyfQ0KcmVnX3ByaWNlX3NpemVfaW50X3llYXIgPC0gbG0oZmxhdF9wcmljZSB+IGZsb29yX3NpemUgKiB5ZWFyX2J1aWx0LCBkYXRhID0gZmxhdHMpDQpwcmVnKHJlZ19wcmljZV9zaXplX2ludF95ZWFyKQ0KYGBgDQoNCioqU1RBVEEqKg0KDQpJbiBTVEFUQSB3ZSByZWNvbW1lbmQgdGhhdCBvbmUgdXNlcyBjLiBvciBpLiB0byBzcGVjaWZ5LCBpbiBzb21lIGluc3RhbmNlcyBpdCBjYW4gY2F1c2UgcHJvYmxlbXMgaWYgdGhleSBhcmUgbm90IHNwZWNpZmllZCBjb3JyZWN0bHkgKGUuZy4sIHRyeSB0aGlzIGNvZGUgYHJlZyBmbGF0X3ByaWNlIGZsb29yX3NpemUjI3llYXJfYnVpbHQpYA0KDQpgYGB7c3RhdGF9DQpyZWcgZmxhdF9wcmljZSBjLmZsb29yX3NpemUjI2MueWVhcl9idWlsdA0KYGBgDQoNCiMjIyMgVmlzdWFsaXppbmcgaW50ZXJhY3Rpb25zIGJldHdlZW4gdHdvIGNvbnRpbnVvdXMgdmFyaWFibGVzDQoNCioqM0QqKg0KDQpgYGB7cn0NCnBlcnNwKHJlZ19wcmljZV9zaXplX2ludF95ZWFyLCANCiAgICAgIHh2YXIgPSAiZmxvb3Jfc2l6ZSIsIA0KICAgICAgeXZhciA9ICJ5ZWFyX2J1aWx0IiwNCiAgICAgIHRoZXRhID0gLTMwLA0KICAgICAgcGhpID0gMTUpDQpgYGANCg0KYGBge3J9DQpsaWJyYXJ5KHBsb3RseSkNCg0KIyBSZW1vdmluZyBOQSdzIA0KZmxhdHNfTkFfcmVtb3ZlZCA8LSBuYS5vbWl0KGZsYXRzKQ0KDQojIENyZWF0aW5nIGEgZ3JpZCByZXByZXNlbnRpbmcgb3VyIHJlZ3Jlc3Npb24gcGxhbmUNCmdyaWRfc2l6ZSA8LSAzMA0Kc2VxX2Zsb29yX3NpemUgPC0gc2VxKG1pbihmbGF0c19OQV9yZW1vdmVkJGZsb29yX3NpemUsIG5hLnJtID0gVCksDQogICAgICAgICAgICAgICAgICAgICAgbWF4KGZsYXRzX05BX3JlbW92ZWQkZmxvb3Jfc2l6ZSwgbmEucm0gPSBUKSwNCiAgICAgICAgICAgICAgICAgICAgICBsZW5ndGgub3V0ID0gZ3JpZF9zaXplKQ0KDQpzZXFfeWVhcl9idWlsdCA8LSBzZXEobWluKGZsYXRzX05BX3JlbW92ZWQkeWVhcl9idWlsdCwgbmEucm0gPSBUKSwNCiAgICAgICAgICAgICAgICAgICAgICBtYXgoZmxhdHNfTkFfcmVtb3ZlZCR5ZWFyX2J1aWx0LCBuYS5ybSA9IFQpLA0KICAgICAgICAgICAgICAgICAgICAgIGxlbmd0aC5vdXQgPSBncmlkX3NpemUpDQoNCnllYXJfc2l6ZSA8LSBleHBhbmQuZ3JpZChmbG9vcl9zaXplID0gc2VxX2Zsb29yX3NpemUsDQogICAgICAgICAgICAgICAgICAgeWVhcl9idWlsdCA9IHNlcV95ZWFyX2J1aWx0KQ0KDQpwcmVkaWN0ZWRfcHJpY2UgPC0gbWF0cml4KHByZWRpY3QocmVnX3ByaWNlX3NpemVfaW50X3llYXIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld2RhdGEgPSB5ZWFyX3NpemUpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICBuY29sID0gZ3JpZF9zaXplLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgbnJvdyA9IGdyaWRfc2l6ZSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGJ5cm93ID0gVFJVRSkgDQoNCg0KcGxvdF9seShkYXRhID0gZmxhdHNfTkFfcmVtb3ZlZCwNCiAgICAgICAgdHlwZSA9ICJzY2F0dGVyM2QiLA0KICAgICAgICB4ID0gfmZsb29yX3NpemUsDQogICAgICAgIHkgPSB+eWVhcl9idWlsdCwNCiAgICAgICAgeiA9IH5mbGF0X3ByaWNlLA0KICAgICAgICBjb2xvciA9IH5sb2NhdGlvbiwNCiAgICAgICAgc2l6ZSA9IEkoMTUwKSkgJT4lDQogIGFkZF9zdXJmYWNlKHggPSBzZXFfZmxvb3Jfc2l6ZSwNCiAgICAgICAgICAgICAgeSA9IHNlcV95ZWFyX2J1aWx0LA0KICAgICAgICAgICAgICB6ID0gcHJlZGljdGVkX3ByaWNlLA0KICAgICAgICAgICAgICBvcGFjaXR5ID0gLjMpDQoNCiAgICAgICAgIA0KYGBgDQoNCioqMkQqKg0KDQpgYGB7cn0NCmxpYnJhcnkobWFyZ2lucykNCg0KcHJlZF9wcmljZV9zaXplX2ludF95ZWFyIDwtIG1hcmdpbnMocmVnX3ByaWNlX3NpemVfaW50X3llYXIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhdCA9IGxpc3QoZmxvb3Jfc2l6ZSA9IGMoMjAsIDIyMCksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeWVhcl9idWlsdCA9IHNlcSgxOTMwLCAyMDEwLCAyMCkNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApDQpwcmVkX3ByaWNlX3NpemVfaW50X3llYXIgPC0gcHJlZF9wcmljZV9zaXplX2ludF95ZWFyICU+JSANCiAgbXV0YXRlKHllYXJfYnVpbHQgPSBmYWN0b3IoeWVhcl9idWlsdCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gc2VxKDE5MzAsIDIwMTAsIDIwKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYXMuY2hhcmFjdGVyKA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlcSgxOTMwLCAyMDEwLCAyMCkNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICkNCiAgICAgICAgICkNCg0KcHJlZF9wcmljZV9zaXplX2ludF95ZWFyICU+JSANCiAgZ2dwbG90KG1hcHBpbmcgPSBhZXMoeCA9IGZsb29yX3NpemUsDQogICAgICAgICAgICAgICAgICAgICAgIHkgPSBmaXR0ZWQsDQogICAgICAgICAgICAgICAgICAgICAgIGNvbG91ciA9IHllYXJfYnVpbHQpKSArDQogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gRikNCmBgYA0KDQoqKlNUQVRBKioNCg0KYGBge3N0YXRhfQ0KcmVnIGZsYXRfcHJpY2UgYy5mbG9vcl9zaXplIyNjLnllYXJfYnVpbHQgDQptYXJnaW5zICwgYXQgKGZsb29yX3NpemUgPSAoMjAoMjAwKTIyMCkgeWVhcl9idWlsdCA9ICgxOTMwKDIwKTIwMTApKQ0KbWFyZ2luc3Bsb3QNCg0KYGBgDQoNCiFbXShpbWFnZXMvU2tqZXJtYmlsZGUlMjAyMDIzLTA2LTA4JTIwMTQ1MzA5LnBuZyl7d2lkdGg9IjcwOSJ9DQoNCiMjIyBFeGFtcGxlOiBJbnRlcmFjdGlvbiBiZXR3ZWVuIGEgY29udGludW91cyBhbmQgYSBjYXRlZ29yaWNhbCB2YXJpYWJsZQ0KDQoxLiAgQWxsb3dpbmcgZm9yIGludGVyYWN0aW9ucyBiZXR3ZWVuIGEgY29udGludW91cyBhbmQgY2F0ZWdvcmljYWwgdmFyaWFibGUsIGNhbiBpbiBlc3NlbmNlIGJlIHRob3VnaHQgb2YgYXMgZm91ciBzZXBhcmF0ZSByZWdyZXNzaW9ucyB3aXRoIHRoZWlyIG93biBpbnRlcmNlcHQgYW5kIHNsb3BlLg0KDQoyLiAgVGhpcyBpcyBldmVuIHRydWUgd2hlbiBhZGRpbmcgYW5vdGhlciBjb250aW51b3VzIGFuZC9vciBjYXRlZ29yaWNhbCB2YXJpYWJsZSwgYnV0IGluIHRoYXQgY2FzZSBhbGwgaW50ZXJhY3Rpb24gdGVybXMgaGF2ZSB0byBiZSBzYXR1cmF0ZWQgKHdoaWNoIHF1aWNrbHkgYmVjb21lcyBjb21wbGljYXRlZCkuDQoNCjMuICBJbiB0aGlzIGV4YW1wbGUgd2UgaGF2ZSBhIGNvbnRpbnVvdXMgdmFyaWFibGUgWDEgYW5kIHR3byBzZXBhcmF0ZSBkdW1teSB2YXJpYWJsZXMgWDIgYW5kIFgzOiAkWV9pID0gXGJldGFfMCArIFxiZXRhXzFYX3sxaX0gKyBcYmV0YV8yIFhfezJpfSArIFxiZXRhXzMgWF97M2l9ICsgXGJldGFfNCBYX3sxaX0gWF97Mml9ICsgXGJldGFfNSBYX3sxaX0gWF97M2l9ICsgXGJldGFfNiBYX3syaX0gKyBcYmV0YV83IFhfezFpfSBYX3syaX0gWF97M2l9JA0KDQogICAgTkI6IFdlIGNvdWxkIHNpbXBseSB1c2UgbG0oYFkgfiBYMSpYMipYMywgZGF0YSA9IGRmKWAgaW4gUiwgYW5kIGByZWcgWSBYMSMjWDIjI1gzYCBpbiBTVEFUQQ0KDQo0LiAgVGhpcyB3b3VsZCB0aGVuIGJlIHRoZSBzYW1lIGFzIHJ1bm5pbmcgYSBzZXBhcmF0ZSByZWdyZXNzaW9uIGZvciBlYWNoIHVuaXF1ZSBncm91cCAoaS5lLiwgZWFjaCB1bmlxdWUgY29tYmluYXRpb24gb2YgQjIgYW5kIEIzKS4NCg0KKipSKioNCg0KYGBge3J9DQpyZWdfcHJpY2VfbG9jYXRpb25faW50X3NpemUgPC0gbG0oZmxhdF9wcmljZSB+IGxvY2F0aW9uKmZsb29yX3NpemUsIGRhdGEgPSBmbGF0cykNCnByZWcocmVnX3ByaWNlX2xvY2F0aW9uX2ludF9zaXplKQ0KYGBgDQoNCioqU1RBVEEqKg0KDQpgYGB7c3RhdGF9DQpyZWcgZmxhdF9wcmljZSBpLmxvY2F0aW9uIyNjLmZsb29yX3NpemUgDQpgYGANCg0KMS4gIFdoZW4gaW50ZXJwcmV0aW5nIHRoaXMgcmVncmVzc2lvbiwgdGhlIGludGVyY2VwdCBvZiBlYWNoIGxvY2F0aW9uIGlzIHRoZSBpbnRlcmNlcHQgKEIwKSArIHRoZSBjb2VmZmljZW50IGZvciB0aGUgbG9jYXRpb24uDQoyLiAgVGhlIHNsb3BlIGZvciBmbG9vcl9zaXplIGZvciBlYWNoIGxvY2F0aW9uIGlzIHRoZSBzbG9wZSBmb3IgZmxvb3Jfc2l6ZSArIHRoZSBzbG9wZSBmb3IgbG9jYXRpb24NCiAgICAxLiAgVGhpcyBpcyBiZWNhdXNlIHRoZSBpbnRlcmFjdGlvbiB0ZXJtIHJlcHJlc2VudHMgdGhlIGNoYW5nZSBpbiBzbG9wZSBwZXIgMSB1bml0IGNoYW5nZQ0KICAgIDIuICBBbmQgZHVtbXkgdmFyaWFibGVzIGFyZSBlaXRoZXIgMCBvciAxLg0KMy4gIFdlIGNhbiBmb3IgZXhhbXBsZSBzZWUgdGhhdCB0aGUgaGlnaGVzdCBpbnRlcmNlcHQgKGkuZS4sIHByZWRpY3RlZCBmbGF0X3ByaWNlIGF0IGZsb29yX3NpemUgPSAwKSBiZWxvbmdzIHRvIGNlbnRyZSAoMTYxIDc1NyksIHdoaWxlIHRoZSBsb3dlc3QgYmVsb25ncyB0byB3ZXN0ICgxNjEgNzU3IC0gMjg4IDExMCA9IC0xMjYzNTMpLg0KNC4gIFdlIGNhbiBhbHNvIHNlZSB0aGF0IHRoZSBsYXJnZXN0IHNsb3BlIGJlbG9uZ3MgdG8gd2VzdCAoNTM0NyArIDI1OTEgPSA3OTM4KSwgd2hpbGUgdGhlIHNtYWxsZXN0IGJlbG9uZ3MgdG8gc291dGggKDUzNDcgLSAxNzUwID0gMzU5NykNCg0KIyMjIyAqKlZpc3VhbGl6aW5nIGludGVyYWN0aW9uIGJldHdlZW4gYSBjYXRlZ29yaWNhbCBhbmQgYSBjb250aW51b3VzIHZhcmlhYmxlKioNCg0KKipSOiBUaGUgTW9kZWwqKg0KDQpgYGB7cn0NCnByZWRfbG9jYXRpb25faW50X2Zsb29yIDwtIG1hcmdpbnMocmVnX3ByaWNlX2xvY2F0aW9uX2ludF9zaXplLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhdCA9IGxpc3QobG9jYXRpb24gPSBjKCJjZW50cmUiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJzb3V0aCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIndlc3QiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJlYXN0IiksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmbG9vcl9zaXplID0gYygyMCwyMjApDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkNCg0KcHJlZF9sb2NhdGlvbl9pbnRfZmxvb3IgJT4lIGdncGxvdChtYXBwaW5nID0gYWVzKHggPSBmbG9vcl9zaXplLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHkgPSBmaXR0ZWQsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb3VyID0gbG9jYXRpb24sDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApICsNCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBGKSANCiAgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgDQpgYGANCg0KKipSOiBSdW5uaW5nIHNlcGFyYXRlIHJlZ3Jlc3Npb25zIGZvciBlYWNoIGxvY2F0aW9uKioNCg0KSGVyZSB5b3UgY2FuIHNlZSB3ZSBnZXQgdGhlIHNhbWUgcGxvdCwgc2hvd2luZyB0aGF0IGl0IGluZGVlZCBpcyBlcXVpdmFsZW50IHRvIHJ1bm5pbmcgZm91ciBzZXBhcmF0ZSByZWdyZXNzaW9ucyAoaW4gdGVybXMgb2YgeW91ciBjb2VmZmljaWVudHMpLg0KDQpgYGB7cn0NCmZsYXRzICU+JSBnZ3Bsb3QobWFwcGluZyA9IGFlcyh4ID0gZmxvb3Jfc2l6ZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB5ID0gZmxhdF9wcmljZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvdXIgPSBsb2NhdGlvbikpICsNCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBGQUxTRSwgZnVsbHJhbmdlID0gVCkNCmBgYA0KDQoqKlNUQVRBKioNCg0KcmVnIGZsYXRfcHJpY2UgaS5sb2NhdGlvbiMjYy5mbG9vcl9zaXplDQoNCm1hcmdpbnMgLCBhdChmbG9vcl9zaXplID0gKDIwKDIwMCkyMjApIGxvY2F0aW9uID0gKDEoMSk0KSkNCg0KbWFyZ2luc3Bsb3QNCg0KYGBge3N0YXRhfQ0KcmVnIGZsYXRfcHJpY2UgaS5sb2NhdGlvbiMjYy5mbG9vcl9zaXplDQoNCm1hcmdpbnMgLCBhdChmbG9vcl9zaXplID0gKDIwKDIwMCkyMjApIGxvY2F0aW9uID0gKDEoMSk0KSkNCm1hcmdpbnNwbG90DQpgYGANCg0KIVtdKGltYWdlcy9Ta2plcm1iaWxkZSUyMDIwMjMtMDYtMDklMjAxMjQxNDIucG5nKXt3aWR0aD0iNjY1In0NCg0KIyMjIEV4ZXJjaXNlcw0KDQoxLiAgUnVuIGEgcmVncmVzc2lvbiB3aXRoIGZsYXQgcHJpY2UgYXMgYSBkZXBlbmRlbnQgdmFyaWFibGUgYW5kIGVuZXJneSBlZmZpY2llbmN5IGFzIGNhdGVnb3JpY2FsIHZhcmlhYmxlDQoNCiAgICAxLiAgT3B0aW9uYWw6IHJ1biB0aGUgc2FtZSByZWdyZXNzaW9uIGJ5IGNyZWF0aW5nIHRoZSBkdW1teSB2YXJpYWJsZXMgYmVmb3JlIGhhbmQsIGFuZCBieSB1c2luZyB0aGUgYnVpbHQgaW4gZHVtbXktdmFyaWFibGUgZnVuY3Rpb25hbGl0eSBpbiB0aGUgbG0oKSBhbmQgcmVnIGNvbW1hbmQuDQoNCjIuICBDaGFuZ2UgdGhlIHJlZmVyZW5jZSBncm91cCBpbiB0aGUgcmVncmVzc2lvbiBtb2RlbA0KDQozLiAgQWRkIGEgY29udGludW91cyBjb3ZhcmlhdGUgdG8gdGhlIHJlZ3Jlc3Npb24gbW9kZWwNCg0KNC4gIFZpc3VhbGl6ZSB0aGUgcmVncmVzc2lvbiBpbiBhIHR3by1kaW1lbnNpb25hbCBwbG90Lg0KDQo1LiAgUnVuIGEgbXVsdGlwbGUgcmVncmVzc2lvbiB3aXRoIGFuIGludGVyYWN0aW9uIGJldHdlZW4gdHdvIGNvbnRpbnVvdXMgdmFyaWFibGVzDQoNCjYuICBJbnRlcnByZXQgdGhlIHJlc3VsdHMNCg0KNy4gIFZpc3VhbGl6ZSB5b3VyIG1vZGVsIGluIDJEDQoNCjguICBSdW4gYSBtdWx0aXBsZSByZWdyZXNzaW9uIHdpdGggYW4gaW50ZXJhY3Rpb24gYmV0d2VlbiBhIGNvbnRpbnVvdXMgYW5kIGEgY2F0ZWdvcmljYWwgdmFyaWFibGUNCg0KOS4gIEludGVycHJldCB0aGUgcmVzdWx0cw0KDQoxMC4gVmlzdWFsaXplIHlvdXIgbW9kZWwgaW4gMkQNCg0KIyMgU2VjdGlvbiAzOiBNZWRpYXRpb24gQW5hbHlzaXMNCg0KMS4gIEluIHRoaXMgc2VjdGlvbiB3ZSdyZSBnb2luZyB0byBhc3Nlc3MgbWVkaWF0aW9uIGJhc2VkIG9uIEJhcm9uIGFuZCBLZW5ueSdzICgxOTY4KQ0KMi4gIEZpcnN0IHdlJ3JlIGdvaW5nIHRvIGdvIHRocm91Z2ggdGhlIG9yaWdpbmFsIHJlZ3Jlc3Npb24gYXBwcm9hY2gNCjMuICBUaGVuIHdlJ3JlIGdvaW5nIHRvIHNob3cgdGhlIGFkanVzdGVkIFNFTS1hcHByb2FjaA0KDQpXZSdyZSBnb2luZyB0byBiZSB1c2luZyB0aGUgKndvcmtvdSp0IGRhdGFzZXQNCg0KIyMjIyBSDQoNCmBgYHtyfQ0Kc2V0d2QoIkM6L1VzZXJzL3NsdXBwL09uZURyaXZlL1Nrcml2ZWJvcmQvTlROVS9NZWhtZXQvUFNZODAwMy9EdW1teV9tb2RlcmF0aW9uX2FuZF9tZWRpYXRpb24iKQ0Kd29ya291dCA8LSByZWFkUkRTKCJ3b3Jrb3V0LnJkcyIpDQpWaWV3KHdvcmtvdXQpDQpgYGANCg0KKipTVEFUQSoqDQoNCmBgYHtzdGF0YX0NCi8vIE5CIGNoYW5nZSBwcm9maWxlLmRvDQp1c2Ugd29ya291dC5kdGEsIGNsZWFyDQpgYGANCg0KIyMgUmVncmVzc2lvbiBBcHByb2FjaDogQmFyb24gYW5kIEtlbm55ICgxOTY4KQ0KDQoxLiAgSW4gYSBtZWRpYXRpb24gYW5hbHlzaXMgd2UgaGF2ZSBhbiBpbmRlcGVuZGVudCB2YXJpYWJsZSAkWCQNCg0KMi4gIEEgbWVkaWF0aW5nIHZhcmlhYmxlICRNJA0KDQozLiAgQW4gYSBkZXBlbmRlbnQgdmFyaWFibGUgJFkkDQoNCjQuICBJbiBtZWRpYXRpb24gd2UgaGF2ZSB0aGUgZGlyZWN0IGVmZmVjdHMgb2YgJFhcbWFwc3RvIE0kLCAkTVxtYXBzdG8gWSQgYW5kIHRoZSBkaXJlY3QgcmVsYXRpb25zaGlwICRjJCB3aGVyZSAkWCBcbWFwc3RvIFkkDQoNCjUuICBMYXN0bHkgd2UgaGF2ZSB0aGUgaW5kaXJlY3QgcmVsYXRpb25zaGlwICRjJyQgd2hlcmUgJFggXG1hcHN0byBZJCwgd2hpbGUgY29udHJvbGxpbmcgZm9yICRNJA0KDQo2LiAgVGhlc2UgcmVsYXRpb25zaGlwcyBhcmUgYXNzZXNzZWQgdGhyb3VnaCBmb3VyIHN0ZXBzDQoNCiAgICAqKk5COioqIE5vdGUgdGhhdCB0aGUgbGFuZ3VhZ2UgaW1wbGllcyBjYXVzYXRpb24sIGJ1dCB0aGF0IGl0IHJlYWxseSByZXF1aXJlcyBleHBlcmltZW50YWwgZGF0YSB0byBiZSBzdXJlDQoNCiMjIyBTdGVwcw0KDQoxLiAgU2ltcGxlIHJlZ3Jlc3Npb25zIGFzc2Vzc2luZyAkYyQsICRYIFxtYXBzdG8gWSQ6DQoNCiAgICAkWSA9IFxiZXRhXzAgKyBcYmV0YV8xIFhfe2l9ICsgZV9pJA0KDQoyLiAgU2ltcGxlIHJlZ3Jlc3Npb24gYXNzZXNzaW5nICRYXG1hcHN0byBNJCAoZWZmZWN0ICphKik6DQoNCiAgICAkTSA9IFxiZXRhXzAgKyBcYmV0YV8xWF97aX0gK2VfaSQNCg0KMy4gIFNpbXBsZSByZWdyZXNzaW9uIGFzc2Vzc2luZyAkTVxtYXBzdG8gWSQgKGVmZmVjdCAqYiopOg0KDQogICAgJFkgPSBcYmV0YV8wICsgXGJldGFfMSBYX3tpfSArIGVfaSQNCg0KNC4gIE11bHRpcGxlIHJlZ3Jlc3Npb24gYXNzZXNzaW5nICRjJyQ6DQoNCiAgICAkWSA9IFxiZXRhXzAgKyBcYmV0YV8xIFhfe2l9ICsgXGJldGFfMiBNX3tpfSArIGVfaSQNCg0KIyMjIEludGVycHJldGluZyBTdGVwcw0KDQoxLiAgRm9yIHRoZXJlIHRvIGJlIG1lZGlhdGlvbiBhbGwgZGlyZWN0IHJlbGF0aW9uc2hpcHMgKHN0ZXBzIDEtMykgbXVzdCBiZSBzaWduaWZpY2FudA0KMi4gIElmIG9uZSAob3IgbXVsdGlwbGUpIG9mIHRoZXNlIGFyZSBub24tc2lnbmlmaWNhbnQgd2UgdXN1YWxseSBhc3N1bWUgdGhlcmUgaXMgbm8gbWVkaWF0aW5nIHJlbGF0aW9uc2hpcA0KMy4gIElmIHN0ZXBzIDEtMyBhcmUgc2lnbmlmaWNhbnQsIHdlIHByb2NlZWQgdG8gc3RlcCA0DQo0LiAgRm9yIHRoZXJlIHRvIGJlIG1lZGlhdGlvbiwgJE0kIHN0aWxsIG5lZWRzIHRvIGhhdmUgYSBzaWduaWZpY2FudCBlZmZlY3QgdXBvbiAkWSQsIHdoZW4gY29udHJvbGxpbmcgZm9yICRYJA0KNS4gIElmICRYJCBzdGlsbCBoYXMgYW4gZWZmZWN0IHVwb24gJFkkIChpLmUuLCBpdCBpcyBzaWduaWZpY2FudCkgd2hlbiBjb250cm9sbGVkIGZvciAkTSQgaXQgc3VnZ2VzdHMgcGFydGlhbCBtZWRpYXRpb24NCjYuICBJZiAkWCQgbm8gbG9uZ2VyIGhhcyBhbiBlZmZlY3QgdXBvbiAkWSQgKGkuZS4sIGl0IGlzIG5vbi1zaWduaWZpY2FudCkgd2hlbiBjb250cm9sbGVkIGZvciAkTSQgaXQgc3VnZ2VzdHMgZnVsbCBtZWRpYXRpb24NCg0KIyMjIENhbGN1bGF0aW5nIGluZGlyZWN0IGVmZmVjdA0KDQoqKkRlbHRhIChkaWZmZXJlbmNlIGluKiogJFxiZXRhXzEkICoqYmV0d2VlbiBzdGVwIDEgYW5kIDQpKioNCg0KJCQNClxiZXRhX3tpbmRpcmVjdH0gPSAgXGJldGFfe3N0ZXBfMX0gLSBcYmV0YV97c3RlcDR9DQokJA0KDQpTb2JlbCBwcm9kdWN0IChwcm9kdWN0IG9mICRcYmV0YSQgZnJvbSAkWFxtYXBzdG8gTSQgYW5kICRNXG1hcHN0byBZJCAqKikqKg0KDQooaS5lLiwgdGhpcyBpcyB0aGUgc2FtZSBhcHByb2FjaCBhcyBjYWxjdWxhdGluZyBhIGNvcnJlbGF0aW9uIG1hdHJpeC9jb3ZhcmlhbmNlIG1hdHJpeCBmcm9tIHBhdGggYW5hbHlzaXMsIHdoZXJlIHdlIG11bHRpcGx5IHRoZSBlZmZlY3Qgb2YgJFgkIG9uICRNJCwgd2l0aCB0aGUgcGFydGlhbCBlZmZlY3Qgb2YgJE0kIG9uICRZJCkNCg0KJCQNClxiZXRhX3tpbmRpcmVjdH0gPSBcYmV0YV97WFxtYXBzdG8gTX0gLSBcYmV0YV97cGFydGlhbE1cbWFwc3RvIFl9DQokJA0KDQojIyMjIENvbnZlbmllbnRseSBTb2JlbCA9IERlbHRhDQoNCiMjIyBJbiBSOg0KDQpZID0gY2Fsb3JpZXMNCg0KWCA9IGF0dHJhY3QNCg0KTSA9IGFwcGVhcg0KDQoqKlN0ZXAgMSoqDQoNCmBgYHtyfQ0Kc3RlcF8xIDwtIGxtKGNhbG9yaWVzIH4gYXR0cmFjdCwgZGF0YSA9IHdvcmtvdXQpDQpwcmVnKHN0ZXBfMSkNCmBgYA0KDQpgYGB7c3RhdGF9DQpyZWcgY2Fsb3JpZXMgYXR0cmFjdA0KYGBgDQoNCldlIGNhbiBzZWUgdGhhdCB0aGUgZWZmZWN0IG9mIGFwcGVhciBvbiBjYWxvcmllcyBpcyBzaWduaWZpY2FudA0KDQoqKlN0ZXAgMioqDQoNCmBgYHtyfQ0Kc3RlcF8yIDwtIGxtKGFwcGVhciB+IGF0dHJhY3QsIGRhdGEgPSB3b3Jrb3V0KQ0KcHJlZyhzdGVwXzIpDQoNCmBgYA0KDQpgYGB7c3RhdGF9DQpyZWcgYXBwZWFyIGF0dHJhY3QNCmBgYA0KDQpXZSBhbHNvIHNlZSB0aGF0IHRoZSBlZmZlY3Qgb2YgYXR0cmFjdCBvbiBhcHBlYXIgaXMgc2lnbmlmaWNhbnQNCg0KKipTdGVwIDMqKg0KDQpgYGB7cn0NCnN0ZXBfMyA8LSBsbShjYWxvcmllcyB+IGFwcGVhciwgZGF0YSA9IHdvcmtvdXQpDQpwcmVnKHN0ZXBfMykNCmBgYA0KDQpgYGB7c3RhdGF9DQpyZWcgY2Fsb3JpZXMgYXBwZWFyDQpgYGANCg0KU2luY2UgYXBwZWFyIGFsc28gaGFzIGEgc2lnbmlmaWNhbnQgZWZmZWN0IHVwb24gYXBwZWFyIHdlIGNhbiBtb3ZlIG9uIHRvIHN0ZXAgNA0KDQoqKlN0ZXAgNCoqDQoNCmBgYHtyfQ0Kc3RlcF80IDwtIGxtKGNhbG9yaWVzIH4gYXR0cmFjdCArIGFwcGVhciwgZGF0YSA9IHdvcmtvdXQpDQpwcmVnKHN0ZXBfNCkNCmBgYA0KDQpgYGB7c3RhdGF9DQpyZWcgY2Fsb3JpZXMgYXR0cmFjdCBhcHBlYXINCmBgYA0KDQpNIGlzIHNpZ25pZmljYW50IHdoaWNoIHBvaW50cyB0b3dhcmRzIG1lZGlhdGlvbi4gU2luY2UgYXR0cmFjdCBoYXMgYmVjb21lIG5vbi1zaWduaWZpY2FudCBpdCBzdWdnZXN0cyBmdWxsIG1lZGlhdGlvbi4NCg0KIyMjIEluZGlyZWN0IGVmZmVjdHMgKHRoaXMgaXMgb25seSB0byBzaG93IHRoZSBjb21wdXRhdGlvbikNCg0KTkI6IFRoZXJlIGlzIGEgcG9wdWxhciBwYWNrYWdlIGZvciB0aGlzIGluIFIsIGJ1dCBpdCByZXF1aXJlcyBhbiBvbGRlciB2ZXJzaW9uIG9mIFINCg0KKipEZWx0YSoqDQoNCmBgYHtyfQ0KZGVsdGEgPC0gc3RlcF8xJGNvZWZmaWNpZW50c1syXSAtIHN0ZXBfNCRjb2VmZmljaWVudHNbMl0NCmRlbHRhDQpgYGANCg0KKipTb2JlbCoqDQoNCmBgYHtyfQ0KYWxwaGEgPC0gc3RlcF8yJGNvZWZmaWNpZW50c1syXSANCmJldGEgPC0gc3RlcF80JGNvZWZmaWNpZW50c1szXQ0Kc29iZWwgPC0gYWxwaGEgKiBiZXRhDQpzb2JlbA0KDQpgYGANCg0KV2UgY2FuIHVzZSBzb2JlbHMgZWZmZWN0IHRvIGNhbGN1bGF0ZSBpdHMgc3RkLmVycm9yLCB3aGljaCBjYW4gZ2l2ZSB1cyBhIHAtc3RhdGlzdGljDQoNCmBgYHtyfQ0Kc3RkLmVycm9yX2FscGhhIDwtIHN1bW1hcnkoc3RlcF8yKVtbImNvZWZmaWNpZW50cyJdXVsyLDJdDQpzdGQuZXJyb3JfYmV0YSA8LSBzdW1tYXJ5KHN0ZXBfNClbWyJjb2VmZmljaWVudHMiXV1bMywyXQ0KDQpzb2JlbF96IDwtIHNxcnQoYWxwaGFeMipzdGQuZXJyb3JfYmV0YV4yICsgDQogICAgICAgICAgICAgICAgICBiZXRhXjIqc3RkLmVycm9yX2FscGhhXjIgKw0KICAgICAgICAgICAgICAgICAgc3RkLmVycm9yX2FscGhhXjIqc3RkLmVycm9yX2JldGFeMikgDQpzb2JlbF96DQoNCkNJX2xvdyA9IHNvYmVsIC0gc29iZWxfeioxLjk2DQpDSV9oaWdoID0gc29iZWwgKyBzb2JlbF96KjEuOTYNCmNhdCgiQ0lfbG93ID0iLCBDSV9sb3csICJDSV9oaWdoID0iLCBDSV9oaWdoKQ0KYGBgDQoNCiMjIFNFTSBBcHByb2FjaA0KDQoxLiAgVGhlcmUgYXJlIG11bHRpcGxlIGFkdmFudGFnZXMgb2YgdXNpbmcgdGhlIFNFTS1hcHByb2FjaCwgYXMgb3Bwb3NlZCB0byB0aGUgcmVncmVzc2lvbiBhcHByb2FjaA0KMi4gIFdoZW4gd2Ugb25seSB1c2Ugb2JzZXJ2ZWQgdmFyaWFibGVzIHdlIHNob3VsZCBnZXQgdGhlIHNhbWUgY29lZmZpY2VudHMgYnV0IHdlIHdpbGwgZ2V0IGEgYml0IGxhcmdlciBzdGQuZXJyb3JzIChhcm91bmQgXDwgLjAwMSB3aXRoIE4gXD4gMjAwKQ0KMy4gIFRoZSBiaWdnZXN0IGFkdmFudGFnZSBpcyB0aGF0IGl0IGlzIHNpbXBsZXIsIHNpbmNlIHlvdSBzaW1wbHkgbmVlZCBhIHNpbmdsZSBtb2RlbA0KNC4gIEl0IGFsc28gYWxsb3dzIHlvdSB0byB1c2UgbGF0ZW50IHZhcmlhYmxlcywgbm90IG9ubHkgb2JzZXJ2ZWQgdmFyaWFibGVzDQoNCmBgYHtyfQ0KIyBpbnN0YWxsLnBhY2thZ2VzKCJsYXZhYW4iLCBkZXBlbmRlbmNpZXMgPSBUKQ0KIyBkZXZ0b29sczo6aW5zdGFsbF9naXRodWIoImlocmtlL3JtZWRzZW0iKQ0KDQpsaWJyYXJ5KHJtZWRzZW0pDQpsaWJyYXJ5KGxhdmFhbikNCg0KYGBgDQoNCmBgYHtzdGF0YX0NCi8vIG5ldCBpbnN0YWxsIGdpdGh1YiwgZnJvbSgiaHR0cHM6Ly9oYWdoaXNoLmdpdGh1Yi5pby9naXRodWIvIikNCi8vIGdpdGh1YiBpbnN0YWxsIG1tb2dsdS9tZWRzZW0NCmBgYA0KDQojIyMgUjogTGF2YWFuIFN5bnRheA0KDQoxLiAgKipQcmVkaWN0OiBcfioqIChlLmcuLCBZIFx+IFgpDQoNCjIuICAqKkluZGljYXRpb246ID1cfioqIChMYXRlbnQgVmFyaWFibGUgXH4gTWVhdXN1cmVkL09ic2VydmVkIFZhcmlhYmxlDQoNCjMuICBcflx+ICoqY292YXJpYW5jZSoqIChlLmcuLCBYIFx+XH4gWCkNCg0KNC4gICoqXH4xIGludGVyY2VwdCoqIG9yIG1lYW4gKGUuZy4sIFggXH4gMSBlc3RpbWF0ZXMgdGhlIG1lYW4gb2YgdmFyaWFibGUgWCkNCg0KNS4gICoqMVwqIGZpeGVzIHBhcmFtZXRlci9sb2FkaW5nKiogdG8gb25lICh1c2VmdWwgc2luZ2xlIGl0ZW0gY29uc3RydWN0cykNCg0KNi4gICoqTkFcKioqICoqZnJlZXMqKiAqKnBhcmFtZXRlcioqIG9yIGxvYWRpbmcgKHVzZWZ1bCB0byBvdmVycmlkZSBkZWZhdWx0IG1hcmtlciBtZXRob2QswqAoZS5nLiwgZiA9XH4gTkFcKnEpDQoNCjcuICAqKmFcKioqICoqbGFiZWxzIHRoZSBwYXJhbWV0ZXIqKiAnYScsIHVzZWQgZm9yIG1vZGVsIGNvbnN0cmFpbnRzwqAoZS5nLiwgZiA9XH4gYVwqcSkNCg0KYGBge3J9DQoNCm1vZGVsIDwtICINCiAgICBhcHBlYXIgfiBhdHRyYWN0DQogICAgY2Fsb3JpZXMgfiBhdHRyYWN0ICsgYXBwZWFyDQoiDQpzZW1fMSA8LSBzZW0obW9kZWwsIGRhdGEgPSB3b3Jrb3V0KQ0Kc3VtbWFyeShzZW1fMSkNCg0KYGBgDQoNCiMjIyAqKlNUQVRBOiBTRU0gc3ludGF4KioNCg0KMS4gIFRoZSBTeW50YXggaXMgcXVpdGUgc2ltaWxhciBpbiBTVEFUQSwgYnV0IGl0cyBhIGJpdCBzaW1wbGVyDQoyLiAgIisiIGlzIHN1YnN0aWR1dGVkIHdpdGggIiAiICgic3BhY2ViYXIiKSBhbmQgYm90aCAiPVx+IiBhbmQgIiBcfiIgYXIgc3Vic3RpdHV0ZWQgd2l0aCAiLVw+IiAoIlw8LSIgYWxzbyB3b3JrcykNCjMuICAqbWVkc2VtLCBpbmRlcCh2YXJuYW1lKSBtZWQodmFybmFtZSkgZGVwKHZhcm5hbWUpIFttY3JlcHMobnVtYmVyKSBzdGFuZCB6bGMgcml0IHJpZF0qDQoNCmBgYHtzdGF0YX0NCnNlbSAoY2Fsb3JpZXMgPC0gYXR0cmFjdCBhcHBlYXIpIChhcHBlYXIgPC0gYXR0cmFjdCkNCnNlbSwgc3RhbmRhcmRpemVkDQpgYGANCg0KIyMjIFVzaW5nIHRoZSBtZWRzZW0gcGFja2FnZQ0KDQojIyMjIEFkanVzdGVkIEJhcm9uIGFuZCBLZW5ueSdzIGFwcHJvYWNoIChkZWZhdWx0KQ0KDQoxLiAgSWYgYm90aCBvciBvbmUgb2YgdGhlIFgtXD5NIGFuZCBNLVw+WSBjb2VmZmljaWVudHMgaXMgbm90IHNpZ25pZmljYW50LCB0aGVyZSBpcyBubyBtZWRpYXRpb24NCg0KMi4gIFdoZW4gYm90aCBvZiB0aGUgWC1cPk0gYW5kIE0tXD5ZIGNvZWZmaWNpZW50cyBhcmUgc2lnbmlmaWNhbnQsIHRoZXJlIGlzICJzb21lIiBtZWRpYXRpb24NCg0KICAgIDEuICBJZiB0aGUgU29iZWwncyB6LXRlc3QgaXMgc2lnbmlmaWNhbnQgYW5kIHRoZSBYLVw+WSBjb2VmZmljaWVudCBpcyBub3Qgc2lnbmlmaWNhbnQsIHRoZW4gdGhlcmUgaXMgY29tcGxldGUgbWVkaWF0aW9uDQoNCiAgICAyLiAgSWYgYm90aCB0aGUgU29iZWwncyB6LXRlc3QgYW5kIHRoZSBYLVw+WSBjb2VmZmljaWVudHMgYXJlIHNpZ25pZmljYW50LCB0aGVuIHRoZXJlIGlzIHBhcnRpYWwgbWVkaWF0aW9uDQoNCiAgICAzLiAgSWYgdGhlIFNvYmVsJ3Mgei10ZXN0IGlzIG5vdCBzaWduaWZpY2FudCBidXQgdGhlIFgtXD5ZIGNvZWZmaWNpZW50IGlzIHNpZ25pZmljYW50LCB0aGVuIHRoZXJlIGlzIHBhcnRpYWwgbWVkaWF0aW9uDQoNCiAgICA0LiAgSWYgbmVpdGhlciBTb2JlbCdzIHotdGVzdCBub3IgdGhlIFgtXD5ZIGNvZWZmaWNpZW50IGFyZSBzaWduaWZpY2FudCwgdGhlbiB0aGVyZSBpcyBwYXJ0aWFsIG1lZGlhdGlvbg0KDQpgYGB7cn0NCm1lZF8xIDwtIHJtZWRzZW0oc2VtXzEsIA0KICAgICAgICBpbmRlcCA9ICJhdHRyYWN0IiwgDQogICAgICAgIG1lZCA9ICJhcHBlYXIiLCANCiAgICAgICAgZGVwID0gImNhbG9yaWVzIiwNCiAgICAgICAgYXBwcm9hY2ggPSBjKCJiayIsICJ6bGMiKSkgDQptZWRfMQ0KYGBgDQoNCmBgYHtzdGF0YX0NCnNlbSAoY2Fsb3JpZXMgPC0gYXR0cmFjdCBhcHBlYXIpIChhcHBlYXIgPC0gYXR0cmFjdCkgDQptZWRzZW0sIGluZGVwKGF0dHJhY3QpIG1lZChhcHBlYXIpIGRlcChjYWxvcmllcykNCg0KDQpgYGANCg0KYGBge3J9DQojaW5zdGFsbC5wYWNrYWdlcygidGlkeVNFTSIpDQpsaWJyYXJ5KHRpZHlTRU0pDQpncmFwaF9zZW0obXNlbV8xKQ0KYGBgDQoNCiMjIyBFeGVyY2lzZXMNCg0KMS4gIFVzZSB0aGUgcmVncmVzc2lvbiBhcHByb2FjaCB0byB0ZXN0IHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBvbmUgaW5kZXBlbmRlbnQsIG9uZSBtZWRpYXRpbmcgYW5kIG9uZSBkZXBlbmRlbnQgdmFyaWFibGUNCjIuICBVc2UgdGhlIFNFTSBhcHByb2FjaCB0byB0ZXN0IHRoZSBzYW1lIG1vZGVsDQozLiAgSW50ZXJwcmV0IHRoZSByZXN1bHRzPyAoSXMgaXQgbm8tLCBzb21lLSBvciBmdWxsIG1lZGlhdGlvbj8pDQo0LiAgVHJ5IHRvIGFkZCBzb21lIGV4dHJhIHZhcmlhYmxlcyB0byB5b3VyIG1vZGVsIHVzaW5nIHRoZSBTRU0gYXBwcm9hY2ggKHRpcDogdGhlIFNFTSBtb2RlbCBpcyB0aGUgb25seSB0aGluZyB0aGF0IGNoYW5nZXMsIHRoZSBtZWRzZW0gdmFyaWFibGVzIGFyZSB0aGUgc2FtZSkNCjUuICBUcnkgYWRkaW5nIGFuIGV4dHJhIG1lZGlhdGluZyByZWxhdGlvbnNoaXAgaW4geW91ciBtb2RlbCAodGlwOiBub3cgeW91IGhhdmUgdG8gcnVuIHR3byBtZWRzZW0gY29tbWFuZHMsIG9uZSB0byB0ZXN0IGVhY2ggbWVkaWF0aW9uKQ0KNi4gIFRyeSB0byBjcmVhdGUgYSBTRU0gbW9kZWwgd2l0aCB0aHJlZSBsYXRlbnQgdmFyaWFibGVzOiBvbmUgaW5kZXBlbmRlbnQsIG9uZSBtZWRpYXRpbmcgYW5kIG9uZSBkZXBlbmRlbnQgbGF0ZW50IHZhcmlhYmxlcw0KICAgIDEuICB0aXA6IHVzZSB0aGUgPVx+IG9wZXJhdG9yIGluIFIsDQogICAgMi4gIEluIFNUQVRBIHVzZSBlaXRoZXIgLVw+IG9yIFw8LSwgYnV0IHJlbWVtYmVyIHRoYXQgb2JzZXJ2ZWQgdmFyaWFibGVzIChpbiB0cmFkaXRpb25hbCBTRU0pLCBhcmUgZnVuY3Rpb25zIG9mIHlvdXIgbGF0ZW50IHZhcmlhYmxlIG5vdCB0aGUgb3RoZXIgd2F5IGFyb3VuZCAoaS5lLiwgaXQgaXMgYWtpbiB0byBtdWx0aXBsZSBzaW1wbGUgcmVncmVzc2lvbnMsIG5vdCBhIHNpbmdsZSBtdWx0aXBsZSByZWdyZXNzaW9uKS4NCg0KIyMgQXBwZW5kaXgNCg0KIyMjIEFwcGVuZGl4OiBJbnRlcnByZXRhdGlvbiAob25seSB1c2VkIHRvIGNhbGwgdmlhIGNhdCgpKQ0KDQpgYGB7ciBlY2hvPUZBTFNFfQ0KaW50ZXJwcmV0YXRpb25fcHJpY2VfbG9jYXRpb24gPC0gIg0KTWVhbiBDZW50cmUgPSA1OTcgNzIxJCBcbg0KTWVhbiBTb3V0aCAgPSA0MjUgNDcwJCAocCA9IC4wMzgpIFxuDQpNZWFuIFdlc3QgICA9IDUxMyA3ODgkIFxuDQpNZWFuIEVhc3QgICA9IDQ5OSA3MjgkIFxuDQpXZSBjYW4gYWxzbyBzZWUgdGhhdCB0aGUgbW9kZWwgYXMgYSB3aG9sZSBpcyBub24tc2lnbmlmaWNhbnQgd2l0aCBhbiBSXjIgYXJvdW5kIDMlDQoNCiINCmBgYA0K